diff --git a/DOCUMENTS/baidu_link_submit_ms.private.api.md b/DOCUMENTS/baidu_link_submit_ms.private.api.md new file mode 100644 index 0000000..1604c12 --- /dev/null +++ b/DOCUMENTS/baidu_link_submit_ms.private.api.md @@ -0,0 +1,79 @@ +# 接口 + +```bash +IP: 192.168.100.50 +PORT: 8000 +HOST: baidu-link-submit-ms.juejin.im +``` + +## 资源创建通知 + +### 请求 + +`POST /v1/events/created` + +### 参数 + +```bash +# 格式 + +Content-Type: application/json; charset=utf-8 + +{ + type, + id +} +``` + +```bash +# 说明 + +type := 'link' | 'column' +# type -> 资源类型,必需 +# link -> 链接 +# column -> 专栏 + +id := +# id -> 资源 ID,必需 +``` + +### 响应 + +```bash +{ + "s": 1, + "m": "success", + "d": [] +} +``` + +### 示例 + +```bash +# 专栏文章创建后 + +POST http://192.168.100.50:8000/v1/events/created HTTP/1.1 +Host: baidu-link-submit-ms.juejin.im +Content-Type: application/json + +{ + "type": "column", + "id": "5ac9dc9af265da23884d5543" +} +``` + +## 资源更新通知 + +### 请求 + +`POST /v1/events/updated` + +其余同上。 + +## 资源删除通知 + +### 请求 + +`POST /v1/events/deleted` + +其余同上。 diff --git a/README.md b/README.md index 2b55513..aee4299 100644 --- a/README.md +++ b/README.md @@ -1,2 +1 @@ -# hi-guoqian-go-ms - +guoqian Go->redis \ No newline at end of file diff --git a/bin/baidu_link_submit_ms b/bin/baidu_link_submit_ms new file mode 100644 index 0000000..a9f18da Binary files /dev/null and b/bin/baidu_link_submit_ms differ diff --git a/config/nginx/baidu_link_submit_ms.private.conf b/config/nginx/baidu_link_submit_ms.private.conf new file mode 100644 index 0000000..73e1b56 --- /dev/null +++ b/config/nginx/baidu_link_submit_ms.private.conf @@ -0,0 +1,58 @@ +# baidu_link_submit_ms.private.conf +# baidu_link_submit_ms nginx config file. +# +# This file auto generated by baidu_link_submit_ms/scripts/init_config.sh, +# [WARRING!] DO NOT change this manualy. +# +# @version 170227:1 +# @author zhangxuhong +# + +upstream baidu_link_submit_ms_private { + server 127.0.0.1:10100; + keepalive 64; +} + +server { + listen 8000; + server_name baidu-link-submit-ms.juejin.im; + + default_type 'text/plain'; # or browser will download page + include /data/apps/nginx/conf/origin/gold.xitu.io_and_juejin.im.conf; + + root /data/repo/baidu_link_submit_ms; + access_log /data/repo/baidu_link_submit_ms/logs/nginx-access.public.log logstash; + error_log /data/repo/baidu_link_submit_ms/logs/nginx-error.public.log; + + client_body_temp_path /data/logs/nginx/client_body_temp/ 1 2; + proxy_temp_path /data/logs/nginx/proxy_temp/ 1 2; + + # X-Juejin-Src for api src trace back + # X-Juejin-Uid for non-login user id + # X-Juejin-Token for api param hash check + add_header 'Access-Control-Allow-Headers' 'X-Juejin-Src,X-Juejin-Uid,X-Juejin-Token' always; + + if ($request_method = OPTIONS ) { + return 200; + } + + # global location settings + location /status { + return 200; + } + + location / { + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Nginx-Proxy true; + proxy_pass http://baidu_link_submit_ms_private; + } + + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + +} \ No newline at end of file diff --git a/config/nginx/baidu_link_submit_ms.public.conf b/config/nginx/baidu_link_submit_ms.public.conf new file mode 100644 index 0000000..d6f839b --- /dev/null +++ b/config/nginx/baidu_link_submit_ms.public.conf @@ -0,0 +1,58 @@ +# baidu_link_submit_ms.public.conf +# baidu_link_submit_ms nginx config file. +# +# This file auto generated by baidu_link_submit_ms/scripts/init_config.sh, +# [WARRING!] DO NOT change this manualy. +# +# @version 170227:1 +# @author zhangxuhong +# + +upstream baidu_link_submit_ms_public { + server 127.0.0.1:10100; + keepalive 64; +} + +server { + listen 80; + server_name baidu-link-submit-ms.juejin.im; + + default_type 'text/plain'; # or browser will download page + include /data/apps/nginx/conf/origin/gold.xitu.io_and_juejin.im.conf; + + root /data/repo/baidu_link_submit_ms; + access_log /data/repo/baidu_link_submit_ms/logs/nginx-access.public.log logstash; + error_log /data/repo/baidu_link_submit_ms/logs/nginx-error.public.log; + + client_body_temp_path /data/logs/nginx/client_body_temp/ 1 2; + proxy_temp_path /data/logs/nginx/proxy_temp/ 1 2; + + # X-Juejin-Src for api src trace back + # X-Juejin-Uid for non-login user id + # X-Juejin-Token for api param hash check + add_header 'Access-Control-Allow-Headers' 'X-Juejin-Src,X-Juejin-Uid,X-Juejin-Token' always; + + if ($request_method = OPTIONS ) { + return 200; + } + + # global location settings + location /status { + return 200; + } + + location / { + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Nginx-Proxy true; + proxy_pass http://baidu_link_submit_ms_public; + } + + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + +} \ No newline at end of file diff --git a/config/nginx/placeholder b/config/nginx/placeholder new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/config/nginx/placeholder @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/config/systemctl/baidu_link_submit_ms.service b/config/systemctl/baidu_link_submit_ms.service new file mode 100644 index 0000000..fe9bf07 --- /dev/null +++ b/config/systemctl/baidu_link_submit_ms.service @@ -0,0 +1,12 @@ +[Unit] +Description = Micro Service API +After = syslog.target network.target + +[Service] +PIDFile = /data/repo/baidu_link_submit_ms/lock/baidu_link_submit_ms.pid +ExecStart = /data/repo/baidu_link_submit_ms/bin/baidu_link_submit_ms beta +ExecReload = /data/repo/baidu_link_submit_ms/bin/baidu_link_submit_ms beta reload +ExecStop = /data/repo/baidu_link_submit_ms/bin/baidu_link_submit_ms beta stop + +[Install] +WantedBy=multi-user.target diff --git a/config/systemctl/placeholder b/config/systemctl/placeholder new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/config/systemctl/placeholder @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/pkg/linux_amd64/github.com/astaxie/beego.a b/pkg/linux_amd64/github.com/astaxie/beego.a new file mode 100644 index 0000000..aa628e3 Binary files /dev/null and b/pkg/linux_amd64/github.com/astaxie/beego.a differ diff --git a/pkg/linux_amd64/github.com/astaxie/beego/config.a b/pkg/linux_amd64/github.com/astaxie/beego/config.a new file mode 100644 index 0000000..f870484 Binary files /dev/null and b/pkg/linux_amd64/github.com/astaxie/beego/config.a differ diff --git a/pkg/linux_amd64/github.com/astaxie/beego/context.a b/pkg/linux_amd64/github.com/astaxie/beego/context.a new file mode 100644 index 0000000..3c67e0c Binary files /dev/null and b/pkg/linux_amd64/github.com/astaxie/beego/context.a differ diff --git a/pkg/linux_amd64/github.com/astaxie/beego/context/param.a b/pkg/linux_amd64/github.com/astaxie/beego/context/param.a new file mode 100644 index 0000000..488f8a8 Binary files /dev/null and b/pkg/linux_amd64/github.com/astaxie/beego/context/param.a differ diff --git a/pkg/linux_amd64/github.com/astaxie/beego/grace.a b/pkg/linux_amd64/github.com/astaxie/beego/grace.a new file mode 100644 index 0000000..6ec0ddd Binary files /dev/null and b/pkg/linux_amd64/github.com/astaxie/beego/grace.a differ diff --git a/pkg/linux_amd64/github.com/astaxie/beego/logs.a b/pkg/linux_amd64/github.com/astaxie/beego/logs.a new file mode 100644 index 0000000..b616322 Binary files /dev/null and b/pkg/linux_amd64/github.com/astaxie/beego/logs.a differ diff --git a/pkg/linux_amd64/github.com/astaxie/beego/session.a b/pkg/linux_amd64/github.com/astaxie/beego/session.a new file mode 100644 index 0000000..8ac34c9 Binary files /dev/null and b/pkg/linux_amd64/github.com/astaxie/beego/session.a differ diff --git a/pkg/linux_amd64/github.com/astaxie/beego/toolbox.a b/pkg/linux_amd64/github.com/astaxie/beego/toolbox.a new file mode 100644 index 0000000..4450fd3 Binary files /dev/null and b/pkg/linux_amd64/github.com/astaxie/beego/toolbox.a differ diff --git a/pkg/linux_amd64/github.com/astaxie/beego/utils.a b/pkg/linux_amd64/github.com/astaxie/beego/utils.a new file mode 100644 index 0000000..1ffcc0f Binary files /dev/null and b/pkg/linux_amd64/github.com/astaxie/beego/utils.a differ diff --git a/pkg/linux_amd64/github.com/garyburd/redigo/internal.a b/pkg/linux_amd64/github.com/garyburd/redigo/internal.a new file mode 100644 index 0000000..37d3900 Binary files /dev/null and b/pkg/linux_amd64/github.com/garyburd/redigo/internal.a differ diff --git a/pkg/linux_amd64/github.com/garyburd/redigo/redis.a b/pkg/linux_amd64/github.com/garyburd/redigo/redis.a new file mode 100644 index 0000000..9a646e4 Binary files /dev/null and b/pkg/linux_amd64/github.com/garyburd/redigo/redis.a differ diff --git a/scripts/ci.sh b/scripts/ci.sh new file mode 100644 index 0000000..2143e01 --- /dev/null +++ b/scripts/ci.sh @@ -0,0 +1,82 @@ +#!/bin/sh +# ci.sh +# This script for build go projects. +# @version 170327:2 +# @author zhangxuhong +# + +# [ci] +echo "-[ci]-" +echo "start" + +# ----------------------------[manual config here]------------------------------ + + +# base config +REPO_SRC=/data/repo/baidu_link_submit_ms +BUILD_TARGET=baidu_link_submit_ms + +# fetch source config +go_packages=( + "github.com/astaxie/beego" +) + +http_proxy="" + + +# deploy config +DEPLOY_SRC=/data/repo +DEPLOY_LOG_SRC=/data/logs +ACTION=$1 +RELEASE_ENV=$2 + +DEV_ENV_LOCATION=( + "root@192.168.0.203" +) +BETA_ENV_LOCATION=( + "root@192.168.0.222" +) +ONLINE_ENV_LOCATION=( + "root@192.168.100.42" # microservice03v + "root@192.168.100.44" # microservice04v + "root@192.168.100.46" # microservice04v +) + + +# ------------------------------------------------------------------------------ + + +# check if release env fit repo src +NOW_PWD=`pwd` +if [ "$NOW_PWD" != "${REPO_SRC}/scripts" ] && [ "$NOW_PWD" != "${REPO_SRC}" ]; then + echo -e "\033[43m[WARRING!] PWD is ${NOW_PWD}, but REPO_SRC is ${REPO_SRC} \033[0m"; + echo -e "please check your REPO_SRC config to make sure that you config this file correctly."; + exit 1; +fi + +# run scripts +SCRIPTS_SRC="${REPO_SRC}/scripts/ci" + +if [ "${ACTION}" == "build" ]; then + . "${SCRIPTS_SRC}/fetch_source.sh" + . "${SCRIPTS_SRC}/build.sh" +elif [ "${ACTION}" == "release" ]; then + . "${SCRIPTS_SRC}/fetch_source.sh" + . "${SCRIPTS_SRC}/build.sh" + . "${SCRIPTS_SRC}/deploy.sh" +elif [ "${ACTION}" == "run_bee" ]; then + . "${SCRIPTS_SRC}/run_bee.sh" +else + echo "usage:" + echo "./ci.sh [action: build/release/run_bee] [beta/online/bee_path]" + echo "" + echo "e.g." + echo "./ci.sh release beta" + echo "" +fi + + + +echo "end" + + diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh new file mode 100644 index 0000000..cbd4489 --- /dev/null +++ b/scripts/ci/build.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# build.sh +# This script for build go projects. +# @version 170227:1 +# @author zhangxuhong +# + +# [config] +echo "-[config]-" + +# ----------------------------[manual config here]------------------------------ + +# REPO_SRC=/data/repo/collection_set_api +# BUILD_TARGET=collection_set_api + +# ------------------------------------------------------------------------------ + +echo -e "\033[34mREPO_SRC set to: ${REPO_SRC}\033[0m" +echo -e "\033[34mBUILD_TARGET set to: ${BUILD_TARGET}\033[0m" + +echo "" +sleep 1 + +# [set env] +echo "-[set env]-" + +# $GOBIN +export GOBIN="${REPO_SRC}/bin" +echo -e "\033[34mGOBIN set to: ${GOBIN}\033[0m" + +# $GOPATH +export GOPATH="${REPO_SRC}" +echo -e "\033[34mGOPATH set to: ${GOPATH}\033[0m" + +echo "" +sleep 1 + +# [check old build target] +echo "-[check old build target]-" +if [ ! -d $GOBIN ]; then mkdir $GOBIN; fi +if [ -f "${GOBIN}/${BUILD_TARGET}" ]; then + echo -e "\033[43m[WARRING!] build target alerady exists, will remove it. \033[0m"; + echo "old build_target detail:" + ls -alh "${GOBIN}/${BUILD_TARGET}"; + oldShaSum=`shasum "${GOBIN}/${BUILD_TARGET}" | awk -F' ' '{print $1}'`; + echo "target sha: ${oldShaSum}"; + rm -rf "${GOBIN}/${BUILD_TARGET}"; + echo "old build target removed."; +fi + +echo "done." +echo "" +sleep 1 + +# [build] +echo "-[build]-" +echo "build start: " +echo "go build -o ${GOBIN}/${BUILD_TARGET}" +cd "${GOPATH}/src" +go build -o "${GOBIN}/${BUILD_TARGET}" + +ls -alh "${GOBIN}/${BUILD_TARGET}" +newShaSum=`shasum "${GOBIN}/${BUILD_TARGET}" | awk -F' ' '{print $1}'`; +echo "target sha: ${newShaSum}"; +if [ "$oldShaSum" == "$newShaSum" ];then + echo -e "\033[43m[WARRING!] old build target shasum is equals to new build target. \033[0m" +fi + +echo "done." + + + diff --git a/scripts/ci/deploy.sh b/scripts/ci/deploy.sh new file mode 100644 index 0000000..41cdc0e --- /dev/null +++ b/scripts/ci/deploy.sh @@ -0,0 +1,181 @@ +#!/bin/sh +# deploy.sh +# This script deploy repo to target env. +# @version 170322:2 +# @author zhangxuhong +# + +# [start deploy] +echo "-[start deploy]-" + +# ----------------------------[manual config here]------------------------------ + +# REPO_SRC=/data/repo/collection_set_api +# BUILD_TARGET=collection_set_api +# DEPLOY_SRC=/data/repo +# DEPLOY_LOG_SRC=/data/logs +# RELEASE_ENV=$1 +# +# DEV_ENV_LOCATION=( +# "root@192.168.0.203" +# ) +# BETA_ENV_LOCATION=( +# "root@192.168.0.204" +# ) +# ONLINE_ENV_LOCATION=( +# "root@192.168.100.32" # microservice03v +# "root@192.168.100.28" # microservice04v +# ) + + + +# ------------------------------------------------------------------------------ + +# final release location +RELEASE_ENV_LOCATION="" + +# release file temp storage location +RELEASE_TEMP_DIR=/data/repo/release + +# program system service name for systemctl +SERVICE_NAME="${BUILD_TARGET}.service" + +# final deploy src +FINAL_DEPLOY_SRC="${DEPLOY_SRC}/${BUILD_TARGET}" + +# nginx config +NGINX_BIN_LOCATION="/data/apps/nginx/sbin/nginx" +NGINX_CONFIG_LOCATION="/data/apps/nginx/conf/vhost/" + +# deploy target machine error handler config +DEPLOY_ERROR_SIGNAL_FILE="${FINAL_DEPLOY_SRC}/logs/deploy_error.s" +DEPLOY_SUCCESS_SIGNAL_FILE="${FINAL_DEPLOY_SRC}/logs/deploy_success.s" +DEPLOY_LOG="${FINAL_DEPLOY_SRC}/logs/deploy.log" + +# print config +echo -e "\033[34mREPO_SRC set to: ${REPO_SRC}\033[0m" +echo -e "\033[34mBUILD_TARGET set to: ${BUILD_TARGET}\033[0m" +echo -e "\033[34mRELEASE_TEMP_DIR set to: ${RELEASE_TEMP_DIR}\033[0m" +echo -e "\033[34mPROJECT WILL DEPLOY TO: ${FINAL_DEPLOY_SRC}\033[0m" +echo -e "\033[34mSERVICE_NAME set to: ${SERVICE_NAME}\033[0m" + +echo "" +sleep 2 + +# [check input] +if [ "$RELEASE_ENV" == "dev" ]; then + RELEASE_ENV_LOCATION=${DEV_ENV_LOCATION[*]} +elif [ "$RELEASE_ENV" == "beta" ]; then + RELEASE_ENV_LOCATION=${BETA_ENV_LOCATION[*]} +elif [ "$RELEASE_ENV" == "online" ]; then + RELEASE_ENV_LOCATION=${ONLINE_ENV_LOCATION[*]} +else + RELEASE_ENV_LOCATION="" +fi +if [ "$RELEASE_ENV_LOCATION" == "" ]; then + echo "please input an avaliable deploy environment [dev/beta/online]"; + echo "example: ./deploy.sh beta"; + exit 1; +fi +echo -e "\033[34mRELEASE_ENV set to: ${RELEASE_ENV} \033[0m" +echo -e "\033[34mRELEASE_ENV_LOCATION set to: \033[0m" +for releaseLocation in ${RELEASE_ENV_LOCATION[*]}; +do + echo -e "\033[34m ${releaseLocation} \033[0m" +done +echo "" +sleep 1 + + +# [check old release file] +echo "-[check old release target]-" +if [ ! -d $RELEASE_TEMP_DIR ]; then mkdir $RELEASE_TEMP_DIR; fi +if [ -f "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz" ]; then + echo -e "\033[43m[WARRING!] release target alerady exists, will remove it. \033[0m"; + ls -alh "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz"; + oldShaSum=`shasum "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz" | awk -F' ' '{print $1}'`; + echo "target sha: ${oldShaSum}"; + rm -f "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz"; + echo "old build target removed."; +fi +echo "" +sleep 1 + +# [compress new release file] +echo "-[compress new release file]-" +cd $REPO_SRC; +tar -zcf "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz" "./" +ls -alh "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz"; +newShaSum=`shasum "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz" | awk -F' ' '{print $1}'`; +echo "target sha: ${newShaSum}"; +if [ "$oldShaSum" == "$newShaSum" ];then + echo -e "\033[43m[WARRING!] old release target shasum is equals to new release target. \033[0m" +fi +echo "" +sleep 1 + + +# [deploy] +echo "-[deploy]-" +echo "- coyp to target machine" +for releaseLocation in ${RELEASE_ENV_LOCATION[*]}; +do + echo -e "\033[34m deploy to ${releaseLocation} \033[0m"; + ssh -T $releaseLocation < +# + +# [config] +echo "-[config]-" + +# ----------------------------[manual config here]------------------------------ + +# REPO_SRC=/data/repo/collection_set_api + +go_packages=( + "github.com/astaxie/beego" + "github.com/garyburd/redigo/redis" +) +# +# http_proxy="http://localhost:8123" + +# ------------------------------------------------------------------------------ + +# init env + +# $GOBIN +export GOBIN="${REPO_SRC}/bin" +echo -e "\033[34mGOBIN set to: ${GOBIN}\033[0m" + +# $GOPATH +export GOPATH="${REPO_SRC}" +echo -e "\033[34mGOPATH set to: ${GOPATH}\033[0m" + + +# print package list + +echo "package list:" +for pkg in ${go_packages[*]}; +do + echo -e "\033[34m${pkg}\033[0m"; +done +echo "" + +if [ "$http_proxy" != "" ]; then + echo "http_proxy set to:" + echo -e "\033[34m${http_proxy}\033[0m"; + echo "http_proxy location info:" + proxyLocation=`http_proxy=${http_proxy} curl -s ip.gs` + echo -e "\033[34m${proxyLocation}\033[0m"; +fi + +echo "" +sleep 1 + + +# [fetch] +echo "-[fetch package]-" +for pkg in ${go_packages[*]}; +do + if [ "$http_proxy" == "" ]; then + echo "go get ${pkg}"; + go get $pkg; + else + echo "http_proxy=${http_proxy} go get ${pkg}"; + http_proxy=${http_proxy} go get $pkg; + fi +done + + + +echo "done." diff --git a/scripts/ci/reactive_service.sh b/scripts/ci/reactive_service.sh new file mode 100644 index 0000000..e40d307 --- /dev/null +++ b/scripts/ci/reactive_service.sh @@ -0,0 +1,183 @@ +#!/bin/sh +# reactive_service.sh +# This script for reactive this projects. +# @version 170327:3 +# @author zhangxuhong +# + +# [config] +echo "-[config]-" + +# ----------------------------[manual config here]------------------------------ + +REPO_SRC=$1 +BUILD_TARGET=$2 +DEPLOY_SRC=$3 +DEPLOY_LOG_SRC=$4 +RELEASE_ENV=$5 + +# ------------------------------------------------------------------------------ + + +# program system service name for systemctl +SERVICE_NAME="${BUILD_TARGET}.service" + +# final deploy src +FINAL_DEPLOY_SRC="${DEPLOY_SRC}/${BUILD_TARGET}" + +# nginx config +NGINX_BIN_LOCATION="/data/apps/nginx/sbin/nginx" +NGINX_CONFIG_LOCATION="/data/apps/nginx/conf/vhost/" + +# deploy target machine error handler config +DEPLOY_ERROR_SIGNAL_FILE="${FINAL_DEPLOY_SRC}/logs/deploy_error.s" +DEPLOY_SUCCESS_SIGNAL_FILE="${FINAL_DEPLOY_SRC}/logs/deploy_success.s" +DEPLOY_LOG="${FINAL_DEPLOY_SRC}/logs/deploy.log" + +# print config +echo -e "\033[34mREPO_SRC set to: ${REPO_SRC}\033[0m" +echo -e "\033[34mBUILD_TARGET set to: ${BUILD_TARGET}\033[0m" +echo -e "\033[34mPROJECT WILL DEPLOY TO: ${FINAL_DEPLOY_SRC}\033[0m" +echo -e "\033[34mSERVICE_NAME set to: ${SERVICE_NAME}\033[0m" + +echo "" +sleep 2 + +# [check input] +if [ "$RELEASE_ENV" == "dev" ]; then + echo "env ok"; +elif [ "$RELEASE_ENV" == "beta" ]; then + echo "env ok"; +elif [ "$RELEASE_ENV" == "online" ]; then + echo "env ok"; +else + echo "please input an avaliable deploy environment [dev/beta/online]"; + echo "example: ./deploy.sh beta"; + exit 1; +fi +echo -e "\033[34mRELEASE_ENV set to: ${RELEASE_ENV} \033[0m" +echo "" +sleep 1 + + +# configure log +if [ ! -d "${DEPLOY_LOG_SRC}/${BUILD_TARGET}" ]; then mkdir "${DEPLOY_LOG_SRC}/${BUILD_TARGET}"; fi +if [ ! -L "${FINAL_DEPLOY_SRC}/logs" ]; then ln -s "${DEPLOY_LOG_SRC}/${BUILD_TARGET}" "${FINAL_DEPLOY_SRC}/logs"; fi + +# remove old deploy signal +if [ -f "${DEPLOY_ERROR_SIGNAL_FILE}" ]; then rm -f "${DEPLOY_ERROR_SIGNAL_FILE}"; fi +if [ -f "${DEPLOY_SUCCESS_SIGNAL_FILE}" ]; then rm -f "${DEPLOY_SUCCESS_SIGNAL_FILE}"; fi + +# deploy start +echo "" | tee -a $DEPLOY_LOG; +echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; +echo "deploy start" | tee -a $DEPLOY_LOG; + +# configure service +if [ ! -L "/etc/systemd/system/${SERVICE_NAME}" ]; then + cp "${FINAL_DEPLOY_SRC}/config/systemctl/${SERVICE_NAME}" "/etc/systemd/system/${SERVICE_NAME}"; +else + rm -f "/etc/systemd/system/${SERVICE_NAME}"; + cp "${FINAL_DEPLOY_SRC}/config/systemctl/${SERVICE_NAME}" "/etc/systemd/system/${SERVICE_NAME}"; +fi + + +# configure nginx +PUBLIC_NGINX_CONF="${FINAL_DEPLOY_SRC}/config/nginx/${BUILD_TARGET}.public.conf" +PRIVATE_NGINX_CONF="${FINAL_DEPLOY_SRC}/config/nginx/${BUILD_TARGET}.private.conf" + +if [ -f "${PUBLIC_NGINX_CONF}" ]; then + ln -s "${PUBLIC_NGINX_CONF}" $NGINX_CONFIG_LOCATION; +fi +if [ -f "${PRIVATE_NGINX_CONF}" ]; then + ln -s "${PRIVATE_NGINX_CONF}" $NGINX_CONFIG_LOCATION; +fi + +# test nginx config +$NGINX_BIN_LOCATION -t 2> "${FINAL_DEPLOY_SRC}/logs/nginx_test.log"; +isNginxOk=`grep 'test is successful' "${FINAL_DEPLOY_SRC}/logs/nginx_test.log" | wc -l `; +if [ "$isNginxOk" != "1" ]; then + touch $DEPLOY_ERROR_SIGNAL_FILE; + echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; + echo "[ERROR!] deploy error with nginx config error, nginx config error is : " | tee -a $DEPLOY_LOG; + cat "${FINAL_DEPLOY_SRC}/logs/nginx_test.log" | tee -a $DEPLOY_LOG; + exit 1; +else + echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; + echo "nginx config is ok:" | tee -a $DEPLOY_LOG; + cat "${FINAL_DEPLOY_SRC}/logs/nginx_test.log" | tee -a $DEPLOY_LOG; +fi + +# stop nginx +$NGINX_BIN_LOCATION -s stop + +# check nginx is stoped +sleep 20; +nginxNum=`ps auxw | grep --color 'nginx' | grep -v grep | wc -l` +if [ "$nginxNum" != "0" ]; then + touch $DEPLOY_ERROR_SIGNAL_FILE; + echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; + echo "[ERROR!] deploy error with nginx stop failed, nginx process num is : ${nginxNum}" | tee -a $DEPLOY_LOG; + exit 1; +else + echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; + echo "nginx stopped" | tee -a $DEPLOY_LOG; +fi + +# restart service +/usr/bin/systemctl daemon-reload; +/usr/bin/systemctl enable ${SERVICE_NAME}; +/usr/bin/systemctl stop ${BUILD_TARGET}; # use start-stop for first time deploy +/usr/bin/systemctl start ${BUILD_TARGET}; + +# check service +sleep 2; +/usr/bin/systemctl status "${BUILD_TARGET}" > "${FINAL_DEPLOY_SRC}/logs/service_status.log"; +serviceStatus=`grep "Active: active" "${FINAL_DEPLOY_SRC}/logs/service_status.log" | wc -l`; +if [ "$serviceStatus" == "0" ]; then + touch $DEPLOY_ERROR_SIGNAL_FILE; + echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; + echo "[ERROR!] deploy error with service start failed, systemctl status :" | tee -a $DEPLOY_LOG; + cat "${FINAL_DEPLOY_SRC}/logs/service_status.log" | tee -a $DEPLOY_LOG; + # restart nginx + $NGINX_BIN_LOCATION; + # check nginx num + nginxNum=`ps auxw | grep --color 'nginx' | grep -v grep | wc -l` + sleep 5; + if [ "$nginxNum" == "0" ]; then + touch $DEPLOY_ERROR_SIGNAL_FILE; + echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; + echo "[ERROR!] deploy error with nginx start failed, nginx process num is : ${nginxNum}" | tee -a $DEPLOY_LOG; + exit 1; + else + echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; + echo "nginx started" | tee -a $DEPLOY_LOG; + fi + exit 1; +else + echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; + echo "service started" | tee -a $DEPLOY_LOG; + cat "${FINAL_DEPLOY_SRC}/logs/service_status.log" | tee -a $DEPLOY_LOG; +fi + +# start nginx +$NGINX_BIN_LOCATION + +# check nginx num +nginxNum=`ps auxw | grep --color 'nginx' | grep -v grep | wc -l`; +sleep 5; +if [ "$nginxNum" == "0" ]; then + touch $DEPLOY_ERROR_SIGNAL_FILE; + echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; + echo "[ERROR!] deploy error with nginx start failed, nginx process num is : ${nginxNum}" | tee -a $DEPLOY_LOG; + exit 1; +else + echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; + echo "nginx started" | tee -a $DEPLOY_LOG; +fi + +# deploy success +echo "success" > $DEPLOY_SUCCESS_SIGNAL_FILE; +echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; +echo "[OK] deploy success." | tee -a $DEPLOY_LOG; +exit 0; diff --git a/scripts/ci/run_bee.sh b/scripts/ci/run_bee.sh new file mode 100644 index 0000000..b495466 --- /dev/null +++ b/scripts/ci/run_bee.sh @@ -0,0 +1,51 @@ +#!/bin/sh +# run_bee.sh +# This script for run beego projects for dev. +# @version 170227:1 +# @author zhangxuhong +# + +# [config] +echo "-[config]-" + +# ----------------------------[manual config here]------------------------------ + +# REPO_SRC=/data/repo/collection_set_api +# BUILD_TARGET=collection_set_api +BEE_PATH=$2 + +# ------------------------------------------------------------------------------ + +echo -e "\033[34mREPO_SRC set to: ${REPO_SRC}\033[0m" +echo -e "\033[34mBUILD_TARGET set to: ${BUILD_TARGET}\033[0m" + +echo "" +sleep 1 + +# [set env] +echo "-[set env]-" + +# $GOBIN +export GOBIN="${REPO_SRC}/bin" +echo -e "\033[34mGOBIN set to: ${GOBIN}\033[0m" + +# $GOPATH +export GOPATH="${REPO_SRC}" +echo -e "\033[34mGOPATH set to: ${GOPATH}\033[0m" + +echo "" + +# run + +if [ "${BEE_PATH}" == "" ]; then + echo "please input bee executable file loacation to run this scripts, like :" + echo "./ci.sh run_bee /data/bin/bee" + exit 1; +fi + +`${BEE_PATH} run ${REPO_SRC}/src` + +echo "done." + + + diff --git a/scripts/config_template/nginx/REPO_NAME.private.conf b/scripts/config_template/nginx/REPO_NAME.private.conf new file mode 100644 index 0000000..ef8cadb --- /dev/null +++ b/scripts/config_template/nginx/REPO_NAME.private.conf @@ -0,0 +1,58 @@ +# REPO_NAME.private.conf +# REPO_NAME nginx config file. +# +# This file auto generated by REPO_NAME/scripts/init_config.sh, +# [WARRING!] DO NOT change this manualy. +# +# @version 170227:1 +# @author zhangxuhong +# + +upstream REPO_NAME_private { + server UPSTREAM_ADDR; + keepalive 64; +} + +server { + listen 8000; + server_name DOMAIN_NAME; + + default_type 'text/plain'; # or browser will download page + include /data/apps/nginx/conf/origin/gold.xitu.io_and_juejin.im.conf; + + root /data/repo/REPO_NAME; + access_log /data/repo/REPO_NAME/logs/nginx-access.public.log logstash; + error_log /data/repo/REPO_NAME/logs/nginx-error.public.log; + + client_body_temp_path /data/logs/nginx/client_body_temp/ 1 2; + proxy_temp_path /data/logs/nginx/proxy_temp/ 1 2; + + # X-Juejin-Src for api src trace back + # X-Juejin-Uid for non-login user id + # X-Juejin-Token for api param hash check + add_header 'Access-Control-Allow-Headers' 'X-Juejin-Src,X-Juejin-Uid,X-Juejin-Token' always; + + if ($request_method = OPTIONS ) { + return 200; + } + + # global location settings + location /status { + return 200; + } + + location / { + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Nginx-Proxy true; + proxy_pass http://REPO_NAME_private; + } + + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + +} \ No newline at end of file diff --git a/scripts/config_template/nginx/REPO_NAME.public.conf b/scripts/config_template/nginx/REPO_NAME.public.conf new file mode 100644 index 0000000..a1859d8 --- /dev/null +++ b/scripts/config_template/nginx/REPO_NAME.public.conf @@ -0,0 +1,58 @@ +# REPO_NAME.public.conf +# REPO_NAME nginx config file. +# +# This file auto generated by REPO_NAME/scripts/init_config.sh, +# [WARRING!] DO NOT change this manualy. +# +# @version 170227:1 +# @author zhangxuhong +# + +upstream REPO_NAME_public { + server UPSTREAM_ADDR; + keepalive 64; +} + +server { + listen 80; + server_name DOMAIN_NAME; + + default_type 'text/plain'; # or browser will download page + include /data/apps/nginx/conf/origin/gold.xitu.io_and_juejin.im.conf; + + root /data/repo/REPO_NAME; + access_log /data/repo/REPO_NAME/logs/nginx-access.public.log logstash; + error_log /data/repo/REPO_NAME/logs/nginx-error.public.log; + + client_body_temp_path /data/logs/nginx/client_body_temp/ 1 2; + proxy_temp_path /data/logs/nginx/proxy_temp/ 1 2; + + # X-Juejin-Src for api src trace back + # X-Juejin-Uid for non-login user id + # X-Juejin-Token for api param hash check + add_header 'Access-Control-Allow-Headers' 'X-Juejin-Src,X-Juejin-Uid,X-Juejin-Token' always; + + if ($request_method = OPTIONS ) { + return 200; + } + + # global location settings + location /status { + return 200; + } + + location / { + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Nginx-Proxy true; + proxy_pass http://REPO_NAME_public; + } + + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + +} \ No newline at end of file diff --git a/scripts/config_template/systemctl/REPO_NAME.beta.service b/scripts/config_template/systemctl/REPO_NAME.beta.service new file mode 100644 index 0000000..e8e2c98 --- /dev/null +++ b/scripts/config_template/systemctl/REPO_NAME.beta.service @@ -0,0 +1,12 @@ +[Unit] +Description = Micro Service API +After = syslog.target network.target + +[Service] +PIDFile = /data/repo/REPO_NAME/lock/BUILD_TARGET.pid +ExecStart = /data/repo/REPO_NAME/bin/BUILD_TARGET beta +ExecReload = /data/repo/REPO_NAME/bin/BUILD_TARGET beta reload +ExecStop = /data/repo/REPO_NAME/bin/BUILD_TARGET beta stop + +[Install] +WantedBy=multi-user.target diff --git a/scripts/config_template/systemctl/REPO_NAME.online.service b/scripts/config_template/systemctl/REPO_NAME.online.service new file mode 100644 index 0000000..f49bc20 --- /dev/null +++ b/scripts/config_template/systemctl/REPO_NAME.online.service @@ -0,0 +1,12 @@ +[Unit] +Description = Micro Service API +After = syslog.target network.target + +[Service] +PIDFile = /data/repo/REPO_NAME/lock/BUILD_TARGET.pid +ExecStart = /data/repo/REPO_NAME/bin/BUILD_TARGET online +ExecReload = /data/repo/REPO_NAME/bin/BUILD_TARGET online reload +ExecStop = /data/repo/REPO_NAME/bin/BUILD_TARGET online stop + +[Install] +WantedBy=multi-user.target diff --git a/scripts/init_config.sh b/scripts/init_config.sh new file mode 100644 index 0000000..2b01d2e --- /dev/null +++ b/scripts/init_config.sh @@ -0,0 +1,145 @@ +#!/bin/bash +# init_config.sh +# init enviroment config scripts. +# @version 170322:1 +# @author zhangxuhong +# + +# ----------------------------[manual config here]------------------------------ + + +# base config +REPO_SRC=/data/repo/baidu_link_submit_ms +REPO_NAME=baidu_link_submit_ms +BUILD_TARGET="${REPO_NAME}" +RELEASE_ENV=$1 # test, beta, online + +# nginx config file type +DOMAIN_NAME="baidu-link-submit-ms.juejin.im" +PUBLIC_UPSTREAM_PORT=13100 +PRIVATE_UPSTREAM_PORT=13100 + + +# ------------------------------------------------------------------------------ + +# default config +NGINX_CONF_TMPL_PUBLIC="REPO_NAME.public.conf" +NGINX_CONF_TMPL_PRIVATE="REPO_NAME.private.conf" +SYSTEMCTL_CONF_TMPL_BETA="REPO_NAME.beta.service" +SYSTEMCTL_CONF_TMPL_RELEASE="REPO_NAME.online.service" + +# auto generated config +# nginx +NGINX_CONFIG_TMPL_FOLDER="${REPO_SRC}/scripts/config_template/nginx" +NGINX_CONFIG_DEPLOY_FOLDER="${REPO_SRC}/config/nginx" +NGINX_CONF_PUBLIC="${REPO_NAME}.public.conf" +NGINX_CONF_PRIVATE="${REPO_NAME}.private.conf" +NGINX_CONF_PUBLIC_ADDR="${NGINX_CONFIG_DEPLOY_FOLDER}/${NGINX_CONF_PUBLIC}" +NGINX_CONF_PRIVATE_ADDR="${NGINX_CONFIG_DEPLOY_FOLDER}/${NGINX_CONF_PRIVATE}" + +if [ "${PUBLIC_UPSTREAM_PORT}" != "" ]; then + UPSTREAM_ADDR_PUBLIC="127.0.0.1:${PUBLIC_UPSTREAM_PORT}" +fi +if [ "${PRIVATE_UPSTREAM_PORT}" != "" ]; then + UPSTREAM_ADDR_PRIVATE="127.0.0.1:${PRIVATE_UPSTREAM_PORT}" +fi + +# systemctl +SYSTEMCTL_CONFIG_TMPL_FOLDER="${REPO_SRC}/scripts/config_template/systemctl" +SYSTEMCTL_CONFIG_DEPLOY_FOLDER="${REPO_SRC}/config/systemctl" +SYSTEMCTL_CONF="${REPO_NAME}.service" +SYSTEMCTL_CONF_ADDR="${SYSTEMCTL_CONFIG_DEPLOY_FOLDER}/${SYSTEMCTL_CONF}" + +# release env +if [ "$RELEASE_ENV" == "dev" ]; then + RELEASE_ENV_LOCATION="$RELEASE_ENV" +elif [ "$RELEASE_ENV" == "beta" ]; then + RELEASE_ENV_LOCATION="$RELEASE_ENV" +elif [ "$RELEASE_ENV" == "online" ]; then + RELEASE_ENV_LOCATION="$RELEASE_ENV" +else + RELEASE_ENV_LOCATION="" +fi +if [ "$RELEASE_ENV_LOCATION" == "" ]; then + echo "please input an avaliable deploy environment [dev/beta/online]"; + echo "example: ./init_config.sh.sh beta"; + exit 1; +fi + +# ------------------------------------------------------------------------------ + +# scripts start + +# check env +NOW_PWD=`pwd` +if [ "$NOW_PWD" != "${REPO_SRC}/scripts" ] && [ "$NOW_PWD" != "${REPO_SRC}" ]; then + echo -e "\033[43m[WARRING!] PWD is ${NOW_PWD}, but REPO_SRC is ${REPO_SRC} \033[0m"; + echo -e "please check your REPO_SRC config to make sure that you config this file correctly."; + exit 1; +fi + + +# [init nginx config] + +# deploy tmpl config to deploy folder +# for public config +if [ "${PUBLIC_UPSTREAM_PORT}" != "" ]; then + # deploy tmpl config to deploy folder + if [ -f "${NGINX_CONF_PUBLIC_ADDR}" ]; then + rm -f "${NGINX_CONF_PUBLIC_ADDR}"; + fi + cp "${NGINX_CONFIG_TMPL_FOLDER}/${NGINX_CONF_TMPL_PUBLIC}" "${NGINX_CONF_PUBLIC_ADDR}"; + # replace config param + sed -i "s/REPO_NAME/${REPO_NAME}/g" "${NGINX_CONF_PUBLIC_ADDR}"; + # replace domain name + sed -i "s/DOMAIN_NAME/${DOMAIN_NAME}/g" "${NGINX_CONF_PUBLIC_ADDR}"; + # replace upstream addr + sed -i "s/UPSTREAM_ADDR/${UPSTREAM_ADDR_PUBLIC}/g" "${NGINX_CONF_PUBLIC_ADDR}"; +fi + +# for private config +if [ "${PRIVATE_UPSTREAM_PORT}" != "" ]; then + # deploy tmpl config to deploy folder + if [ -f "${NGINX_CONF_PRIVATE_ADDR}" ]; then + rm -f "${NGINX_CONF_PRIVATE_ADDR}"; + fi + cp "${NGINX_CONFIG_TMPL_FOLDER}/${NGINX_CONF_TMPL_PRIVATE}" "${NGINX_CONF_PRIVATE_ADDR}" + # replace config param + sed -i "s/REPO_NAME/${REPO_NAME}/g" "${NGINX_CONF_PRIVATE_ADDR}"; + # replace domain name + sed -i "s/DOMAIN_NAME/${DOMAIN_NAME}/g" "${NGINX_CONF_PRIVATE_ADDR}"; + # replace upstream addr + sed -i "s/UPSTREAM_ADDR/${UPSTREAM_ADDR_PRIVATE}/g" "${NGINX_CONF_PRIVATE_ADDR}"; +fi + + +# [init systemctl config] + +# deploy tmpl config to deploy folder +# for beta service +if [ "${RELEASE_ENV_LOCATION}" == "beta" ]; then + if [ -f "${SYSTEMCTL_CONF_ADDR}" ]; then + rm -f "${SYSTEMCTL_CONF_ADDR}"; + fi + cp "${SYSTEMCTL_CONFIG_TMPL_FOLDER}/${SYSTEMCTL_CONF_TMPL_BETA}" "${SYSTEMCTL_CONF_ADDR}" + # replace repo name + sed -i "s/REPO_NAME/${REPO_NAME}/g" "${SYSTEMCTL_CONF_ADDR}"; + # replace build target + sed -i "s/BUILD_TARGET/${BUILD_TARGET}/g" "${SYSTEMCTL_CONF_ADDR}"; +fi + +# for online service +if [ "${RELEASE_ENV_LOCATION}" == "online" ]; then + if [ -f "${SYSTEMCTL_CONF_ADDR}" ]; then + rm -f "${SYSTEMCTL_CONF_ADDR}"; + fi + cp "${SYSTEMCTL_CONFIG_TMPL_FOLDER}/${SYSTEMCTL_CONF_TMPL_RELEASE}" "${SYSTEMCTL_CONF_ADDR}" + # replace repo name + sed -i "s/REPO_NAME/${REPO_NAME}/g" "${SYSTEMCTL_CONF_ADDR}"; + # replace build target + sed -i "s/BUILD_TARGET/${BUILD_TARGET}/g" "${SYSTEMCTL_CONF_ADDR}"; +fi + + + +exit 0; diff --git a/src/base/init.go b/src/base/init.go new file mode 100644 index 0000000..d3aa125 --- /dev/null +++ b/src/base/init.go @@ -0,0 +1,11 @@ +package base + +import ( + "github.com/astaxie/beego" +) + +const configFilePath = "/data/repo/baidu_link_submit_ms/src/config/app.conf" + +func init() { + beego.LoadAppConfig("ini", configFilePath) +} diff --git a/src/config/app.conf b/src/config/app.conf new file mode 100644 index 0000000..8da8584 --- /dev/null +++ b/src/config/app.conf @@ -0,0 +1,21 @@ +appname = hi_guoqian_go_ms +httpport = 13100 +runmode = dev +autorender = false +copyrequestbody = true +EnableDocs = false + +[dev] +redisAddress = 192.168.0.204:6379 +redisDb = 0 +redisPassword= + +[beta] +redisAddress = 192.168.0.204:6379 +redisDb = 0 +redisPassword= + +[proc] +redisAddress = 192.168.100.15:6379 +redisDb = 1 +redisPassword=rcASeLT1NayQp59B4UiM diff --git a/src/controllers/event.go b/src/controllers/event.go new file mode 100644 index 0000000..deaf844 --- /dev/null +++ b/src/controllers/event.go @@ -0,0 +1,59 @@ +package controllers + +import ( + . "errors" + "github.com/astaxie/beego" + . "middlewares" + . "models" +) + +var ( + baseUrl string = "https://juejin.im" + typePathMap map[string]string = map[string]string{ + "link": "/entry/", + "column": "/post/", + } +) + +type EventController struct { + beego.Controller +} + +//start +func (this *EventController) Contribution() { + ret, err := IncrRedis("hi:guoqian") + controller := &BeegoController{Controller: this.Controller} + if err != nil { + if err.Error() == M_NO_RESULT { + controller.RenderOutput(EmptyErr(nil)) + return + } else { + controller.RenderOutput(ServerErr(err.Error())) + return + } + }else{ + controller.RenderOutput(Success(ret)) + return + } + +} + + +func (this *EventController) Second() { + ret, err := GetRedis("hi:guoqian") + controller := &BeegoController{Controller: this.Controller} + if err != nil { + if err.Error() == M_NO_RESULT { + controller.RenderOutput(EmptyErr(nil)) + return + } else { + controller.RenderOutput(ServerErr(err.Error())) + return + } + }else{ + controller.RenderOutput(Success(ret)) + return + } + +} +//end \ No newline at end of file diff --git a/src/main.go b/src/main.go new file mode 100644 index 0000000..e838b64 --- /dev/null +++ b/src/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "github.com/astaxie/beego" + _ "base" + _ "models" + _ "routers" +) + +func main() { + initLog() + beego.Run() +} + +func initLog() { + name := beego.AppConfig.String("appname") + logFilePath := "/data/repo/" + name + "/logs/" + name + ".log" + beego.SetLogger("file", `{"filename":"` + logFilePath + `","level":2,"daily":true,"maxdays":10}`) + if beego.AppConfig.String("runmode") != "dev" { + beego.BeeLogger.DelLogger("console") + } + beego.BeeLogger.EnableFuncCallDepth(true) + beego.SetLogFuncCall(true) + beego.BeeLogger.Async() +} diff --git a/src/middlewares/input_adapter.go b/src/middlewares/input_adapter.go new file mode 100644 index 0000000..226fbbb --- /dev/null +++ b/src/middlewares/input_adapter.go @@ -0,0 +1,39 @@ +package middleware + +import ( + "github.com/astaxie/beego" +) + +type BeegoController struct { + Controller beego.Controller +} + +func (c *BeegoController) GetQuery(key string) string { + return c.Controller.Input().Get(key) +} +func (c *BeegoController) GetForm(key string) string { + return c.Controller.Input().Get(key) +} +func (c *BeegoController) GetHeader(key string) string { + return c.Controller.Ctx.Input.Header(key) +} +func (c *BeegoController) GetCookie(key string) string { + return c.Controller.Ctx.Input.Cookie(key) +} +func (c *BeegoController) GetBody() []byte { + return c.Controller.Ctx.Input.RequestBody +} +func (c *BeegoController) GetPath(key string) string { + return c.Controller.GetString(":" + key) +} +func (c *BeegoController) GetArray(key string) []string { + array := make([]string, 0) + c.Controller.Ctx.Input.Bind(&array, key) + return array +} + +func (c *BeegoController) RenderOutput(ret *RenderStruct) { + c.Controller.Ctx.Output.Status = ret.Status + c.Controller.Data["json"] = ret + c.Controller.ServeJSON() +} diff --git a/src/middlewares/request_mw.go b/src/middlewares/request_mw.go new file mode 100644 index 0000000..10e2e70 --- /dev/null +++ b/src/middlewares/request_mw.go @@ -0,0 +1,306 @@ +package middleware + +import ( + "encoding/json" + "strconv" + "time" +) + +const ( + TYPE_STRING = iota + TYPE_INT + TYPE_FLOAT + TYPE_BOOLEAN + TYPE_TIME + TYPE_ARRAY + TYPE_JSON_OBJECT +) +const ( + POS_QUERY = iota + POS_HEADER + POS_BODY_FORM + POS_BODY_JSON + POS_PATH + POS_COOKIE +) +const ( + TIME_LAYOUT = "2006-01-02T15:04:05Z" +) + +type InputInterface interface { + GetQuery(key string) string + GetForm(key string) string + GetHeader(key string) string + GetCookie(key string) string + GetBody() []byte + GetPath(key string) string + GetArray(key string) []string + RenderOutput(r *RenderStruct) +} + +type InputContainer struct { + simpleMap map[string]interface{} + objectMap map[string][]byte + arrayMap map[string][]string +} + +type InputRule struct { + Name string + Description string + Position int + Type int + //此处有蹊跷 + Limit []string + Necessary bool + Max int + Min int + Default interface{} +} + +type CheckError struct { + Missing string `json:"missing" xml:"missing"` + Illegal string `json:"illegal" xml:"illegal"` +} + +func (c *CheckError) Error() string { + return "input error" +} + +//must use this func to create a new container +func NewContainer() *InputContainer { + return &InputContainer{ + simpleMap: make(map[string]interface{}), + objectMap: make(map[string][]byte), + arrayMap: make(map[string][]string), + } +} + +func (i *InputContainer) CheckInput(input InputInterface, rules []*InputRule) *CheckError { + for _, rule := range rules { + //check special input type + switch rule.Type { + case TYPE_ARRAY: + arr := input.GetArray(rule.Name) + if rule.Necessary && len(arr) <= 0 { + return &CheckError{ + Missing: rule.Name, + } + } + if rule.Max > 0 { + if len(arr) > rule.Max { + return &CheckError{ + Illegal: rule.Name, + } + } + } + if rule.Min > 0 { + if len(arr) < rule.Min { + return &CheckError{ + Illegal: rule.Name, + } + } + } + i.arrayMap[rule.Name] = arr + case TYPE_JSON_OBJECT: + var bytes []byte + switch rule.Position { + default: + fallthrough + case POS_BODY_JSON: + bytes = input.GetBody() + case POS_QUERY: + bytes = []byte(input.GetQuery(rule.Name)) + case POS_BODY_FORM: + bytes = []byte(input.GetForm(rule.Name)) + case POS_HEADER: + bytes = []byte(input.GetHeader(rule.Name)) + case POS_COOKIE: + bytes = []byte(input.GetCookie(rule.Name)) + } + if rule.Necessary && len(bytes) <= 0 { + return &CheckError{ + Missing: rule.Name, + } + } else if len(bytes) <= 0 { + continue + } + err := json.Unmarshal(bytes, &map[string]interface{}{}) + if err != nil { + return &CheckError{ + Illegal: rule.Name, + } + } + i.objectMap[rule.Name] = bytes + default: + //check normal input type + var val string + switch rule.Position { + case POS_PATH: + val = input.GetPath(rule.Name) + default: + fallthrough + case POS_QUERY: + val = input.GetQuery(rule.Name) + case POS_BODY_FORM: + val = input.GetForm(rule.Name) + case POS_HEADER: + val = input.GetHeader(rule.Name) + case POS_COOKIE: + val = input.GetCookie(rule.Name) + } + if rule.Necessary && len(val) <= 0 { + return &CheckError{ + Missing: rule.Name, + } + } else if len(val) <= 0 { + i.simpleMap[rule.Name] = rule.Default + } else { + res, err := checkValue(rule, val) + if err != nil { + return err + } + i.simpleMap[rule.Name] = res + } + } + } + return nil +} + +func checkValue(rule *InputRule, val string) (interface{}, *CheckError) { + limit := len(rule.Limit) <= 0 + if !limit { + for _, i := range rule.Limit { + if val == i { + limit = true + break + } + } + if !limit { + return nil, &CheckError{ + Illegal: rule.Name, + } + } + } + switch rule.Type { + default: + fallthrough + case TYPE_STRING: + if rule.Max > 0 { + if len(val) > rule.Max { + return nil, &CheckError{ + Illegal: rule.Name, + } + } + } + if rule.Min > 0 { + if len(val) < rule.Min { + return nil, &CheckError{ + Illegal: rule.Name, + } + } + } + return val, nil + case TYPE_INT: + intVal, err := strconv.Atoi(val) + if err != nil { + return nil, &CheckError{ + Illegal: rule.Name, + } + } + if rule.Max > 0 { + if intVal > rule.Max { + return nil, &CheckError{ + Illegal: rule.Name, + } + } + } + if rule.Min > 0 { + if intVal < rule.Min { + return nil, &CheckError{ + Illegal: rule.Name, + } + } + } + return intVal, nil + case TYPE_FLOAT: + floatVal, err := strconv.ParseFloat(val, 64) + if err != nil { + return nil, &CheckError{ + Illegal: rule.Name, + } + } + if rule.Max > 0 { + if floatVal > float64(rule.Max) { + return nil, &CheckError{ + Illegal: rule.Name, + } + } + } + if rule.Min > 0 { + if floatVal < float64(rule.Min) { + return nil, &CheckError{ + Illegal: rule.Name, + } + } + } + return floatVal, nil + case TYPE_BOOLEAN: + booleanVal, err := strconv.ParseBool(val) + if err != nil { + return nil, &CheckError{ + Illegal: rule.Name, + } + } + return booleanVal, nil + case TYPE_TIME: + t, err := time.Parse(TIME_LAYOUT, val) + if err != nil { + return nil, &CheckError{ + Illegal: rule.Name, + } + } + return t, nil + } +} + +func (i *InputContainer) GetInt(key string) int { + if res, ok := i.simpleMap[key].(int); ok { + return res + } + return 0 +} + +func (i *InputContainer) GetBoolean(key string) bool { + if res, ok := i.simpleMap[key].(bool); ok { + return res + } + return false +} + +func (i *InputContainer) GetFloat(key string) float64 { + if res, ok := i.simpleMap[key].(float64); ok { + return res + } + return 0 +} + +func (i *InputContainer) GetString(key string) string { + if res, ok := i.simpleMap[key].(string); ok { + return res + } + return "" +} + +func (i *InputContainer) GetArray(key string) []string { + return i.arrayMap[key] +} +func (i *InputContainer) GetObject(key string, obj interface{}) error { + bytes := i.objectMap[key] + return json.Unmarshal(bytes, obj) +} +func (i *InputContainer) GetTime(key string) time.Time { + if res, ok := i.simpleMap[key].(time.Time); ok { + return res + } + return time.Time{} +} diff --git a/src/middlewares/return_struct.go b/src/middlewares/return_struct.go new file mode 100644 index 0000000..c159528 --- /dev/null +++ b/src/middlewares/return_struct.go @@ -0,0 +1,112 @@ +package middleware + +import ( + "github.com/astaxie/beego" + "net/http" +) + +const ( + S_UNKNOWN_ERROR = iota + S_OK + S_NO_RESULT + S_ILLEGAL_TOKEN + S_WRONG_INPUT + S_WRONG_EXEC_RESULT + S_TOKEN_EXPIRE +) +const ( + M_OK = "success" + M_NO_RESULT = "no result" + M_ILLEGAL_TOKEN = "illegal token" + M_TOKEN_EXPIRE = "token expired" + M_ILLEGAL_SESSION = "illegal session" + M_WRONG_INPUT = "wrong input" + M_WRONG_EXEC_RESULT = "exec error" +) + +type RenderStruct struct { + Status int `json:"-"` + S int `json:"s"` + M string `json:"m"` + D interface{} `json:"d"` +} + +func Success(list interface{}) (r *RenderStruct) { + r = new(RenderStruct) + r.Status = http.StatusOK + r.S = S_OK + r.M = M_OK + if list == nil { + list = []interface{}{} + } + r.D = list + return +} + +func EmptyErr(list interface{}) (r *RenderStruct) { + r = new(RenderStruct) + r.Status = http.StatusOK + r.S = S_NO_RESULT + r.M = M_NO_RESULT + if list == nil { + list = []interface{}{} + } + r.D = list + return +} + +func InputErr(data interface{}) (r *RenderStruct) { + r = new(RenderStruct) + r.Status = http.StatusBadRequest + if data == nil { + data = []interface{}{} + } + r.S = S_WRONG_INPUT + r.M = M_WRONG_INPUT + r.D = data + if beego.BConfig.RunMode != "dev" { + r.D = []interface{}{} + } + return +} + +func NormalErr(status int, s int, msg string, d interface{}) (r *RenderStruct) { + r = new(RenderStruct) + r.Status = status + r.S = s + r.M = msg + if d == nil { + d = []interface{}{} + } + r.D = d + return +} + +func ServerErr(message string) (r *RenderStruct) { + r = new(RenderStruct) + r.Status = http.StatusInternalServerError + r.S = S_WRONG_EXEC_RESULT + r.M = message + if len(message) <= 0 { + r.M = M_WRONG_EXEC_RESULT + } + r.D = []interface{}{} + return +} + +func TokenErr(errorType int) (r *RenderStruct) { + r = new(RenderStruct) + r.Status = http.StatusForbidden + switch errorType { + case S_TOKEN_EXPIRE: + r.S = S_TOKEN_EXPIRE + r.M = M_TOKEN_EXPIRE + default: + fallthrough + case S_ILLEGAL_TOKEN: + r.S = S_ILLEGAL_TOKEN + r.M = M_ILLEGAL_TOKEN + } + r.D = []interface{}{} + return +} diff --git a/src/models/cache.go b/src/models/cache.go new file mode 100644 index 0000000..9a5b370 --- /dev/null +++ b/src/models/cache.go @@ -0,0 +1,65 @@ +package models + +import ( + "github.com/astaxie/beego" + "github.com/garyburd/redigo/redis" + "time" +) + +var RedisPool *redis.Pool + +func init() { + address := beego.AppConfig.String("redisAddress") + password := beego.AppConfig.String("redisPassword") + dbNum := beego.AppConfig.String("redisDb") + dialFunc := func() (c redis.Conn, err error) { + // c, err = redis.Dial("tcp", address) + // func DialTimeout(network, address string, connectTimeout, readTimeout, writeTimeout time.Duration) (Conn, error) + c, err = redis.DialTimeout("tcp", address, 3*time.Second, 3*time.Second, 3*time.Second) + if err != nil { + return nil, err + } + + if beego.AppConfig.String("redisPassword") != "" { + if _, err := c.Do("AUTH", password); err != nil { + c.Close() + return nil, err + } + } + + _, selecterr := c.Do("SELECT", dbNum) + if selecterr != nil { + c.Close() + return nil, selecterr + } + return + } + // initialize a new pool + RedisPool = &redis.Pool{ + MaxIdle: 100, + MaxActive: 50, + IdleTimeout: 180 * time.Second, + Dial: dialFunc, + } +} + +func SetRedis(key string, value []byte) error { + conn := RedisPool.Get() + defer conn.Close() + conn.Send("SET", key, value) + return conn.Flush() +} + +func GetRedis(key string) (int64, error) { + conn := RedisPool.Get() + defer conn.Close() + ret, err := redis.Int64(conn.Do("GET", key)) + return ret, err +} + +func IncrRedis(key string) (int64, error) { + conn := RedisPool.Get() + defer conn.Close() + ret, err := redis.Int64(conn.Do("INCR", key)) + return ret, err +} diff --git a/src/routers/router.go b/src/routers/router.go new file mode 100644 index 0000000..14870d7 --- /dev/null +++ b/src/routers/router.go @@ -0,0 +1,19 @@ +package routers + +import ( + "net/http" + "github.com/astaxie/beego" + . "controllers" +) + +func init() { + eventController := EventController{} + namespace := beego.NewNamespace("/v1", + beego.NSRouter("/second", &eventController, "get:Second"), + beego.NSRouter("/contribution", &eventController, "post:Contribution"), + ) + beego.AddNamespace(namespace) + beego.ErrorHandler("404", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotFound) + }) +}