This commit is contained in:
crusader 2017-11-09 18:14:57 +09:00
commit 02b77bb617
15 changed files with 588 additions and 0 deletions

68
.gitignore vendored Normal file
View File

@ -0,0 +1,68 @@
# Created by .ignore support plugin (hsz.mobi)
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Go template
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
.idea/
*.iml
vendor/
glide.lock
.DS_Store
dist/
debug

32
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,32 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"type": "go",
"request": "launch",
"mode": "debug",
"remotePath": "",
"port": 2345,
"host": "127.0.0.1",
"program": "${workspaceRoot}/main.go",
"env": {},
"args": [],
"showLog": true
},
{
"name": "File Debug",
"type": "go",
"request": "launch",
"mode": "debug",
"remotePath": "",
"port": 2345,
"host": "127.0.0.1",
"program": "${fileDirname}",
"env": {},
"args": [],
"showLog": true
}
]
}

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
// Place your settings in this file to overwrite default and user settings.
{
}

16
conf/conf.go Normal file
View File

@ -0,0 +1,16 @@
package conf
import (
oogc "git.loafle.net/overflow/overflow_gateway_config"
)
var Config Conf
type Conf struct {
Server oogc.Server `json:"server" yaml:"server" toml:"server"`
Auth oogc.Auth `json:"auth" yaml:"auth" toml:"auth"`
Websocket oogc.Websocket `json:"websocket" yaml:"websocket" toml:"websocket"`
GRPC oogc.GRPC `json:"gRPC" yaml:"gRPC" toml:"gRPC"`
Redis oogc.Redis `json:"redis" yaml:"redis" toml:"redis"`
Handlers map[string]oogc.Handler `json:"handlers" yaml:"handlers" toml:"handlers"`
}

63
config.json Normal file
View File

@ -0,0 +1,63 @@
{
"server": {
"addr": ":19090",
"tls": false
},
"auth": {
"signingKey": "tWB0lUXiCwX4U3qsJZcZ10mKvEH793RHkTJDbDuZVshQTk4uNB6ck59UQ96lhsRi4XNUiEnlIbP8XYQMPabeNtERX3iyHeDcwocgUVAor1nkAajYeq1gNyJszGpMhEOT"
},
"websocket": {
"handshakeTimeout": 0,
"readBufferSize": 8192,
"writeBufferSize": 8192,
"enableCompression": false
},
"gRPC": {
"addr": "127.0.0.1:50006",
"tls": false,
"pool": {
"maxIdle": 1,
"maxCapacity": 3,
"idleTimeout": 240,
"wait": false
}
},
"redis": {
"network": "tcp",
"addr": "192.168.1.50:6379",
"tls": false,
"pool": {
"maxIdle": 1,
"maxCapacity": 3,
"idleTimeout": 240,
"wait": false
}
},
"handlers": {
"web": {
"entry": "/web",
"socket": {
"maxMessageSize": 8192,
"writeTimeout": 0,
"readTimeout": 0,
"pongTimeout": 60,
"pingTimeout": 10,
"pingPeriod": 10,
"binaryMessage": false
}
},
"file": {
"entry": "/file",
"socket": {
"maxMessageSize": 8192,
"writeTimeout": 0,
"readTimeout": 0,
"pongTimeout": 60,
"pingTimeout": 10,
"pingPeriod": 10,
"binaryMessage": false
}
}
}
}

16
external/external.go vendored Normal file
View File

@ -0,0 +1,16 @@
package external
import (
"git.loafle.net/overflow/overflow_gateway_app/external/grpc"
"git.loafle.net/overflow/overflow_gateway_app/external/redis"
)
func ExternalInit() {
grpc.ExternalInit()
redis.ExternalInit()
}
func ExternalDestroy() {
grpc.ExternalDestroy()
redis.ExternalDestroy()
}

35
external/grpc/client.go vendored Normal file
View File

@ -0,0 +1,35 @@
package grpc
import (
"context"
"fmt"
"strings"
ooas "git.loafle.net/overflow/overflow_api_server/golang"
)
func Exec(ctx context.Context, method string, params []string) (string, error) {
if nil == grpcPool {
return "", fmt.Errorf("App: GRPC Pool is not initialized")
}
var client interface{}
var err error
if client, err = grpcPool.Get(); nil != err {
return "", err
}
defer grpcPool.Put(client)
sm := strings.Split(method, ".")
si := &ooas.ServerInput{
Target: sm[0],
Method: sm[1],
Params: params,
}
var so *ooas.ServerOutput
if so, err = client.(ooas.OverflowApiServerClient).Exec(ctx, si); nil != err {
return "", err
}
return so.Result, nil
}

49
external/grpc/pool.go vendored Normal file
View File

@ -0,0 +1,49 @@
package grpc
import (
"fmt"
cgp "git.loafle.net/commons_go/grpc_pool"
"git.loafle.net/commons_go/logging"
ooas "git.loafle.net/overflow/overflow_api_server/golang"
"git.loafle.net/overflow/overflow_gateway_app/conf"
"google.golang.org/grpc"
)
var grpcPool cgp.Pool
func ExternalInit() {
ph := &grpcPoolHandlers{}
ph.MaxCapacity = conf.Config.GRPC.Pool.MaxCapacity
ph.MaxIdle = conf.Config.GRPC.Pool.MaxIdle
ph.IdleTimeout = conf.Config.GRPC.Pool.IdleTimeout
ph.Wait = conf.Config.GRPC.Pool.Wait
grpcPool = cgp.New(ph)
if err := grpcPool.Start(); nil != err {
logging.Logger().Panic(fmt.Sprintf("App: %v", err))
return
}
}
func ExternalDestroy() {
if nil != grpcPool {
grpcPool.Stop()
}
}
type grpcPoolHandlers struct {
cgp.PoolHandlers
}
func (h *grpcPoolHandlers) Dial() (*grpc.ClientConn, interface{}, error) {
var err error
conn, err := grpc.Dial(conf.Config.GRPC.Addr, grpc.WithInsecure())
if nil != err {
return nil, nil, err
}
c := ooas.NewOverflowApiServerClient(conn)
return conn, c, nil
}

42
external/redis/pool.go vendored Normal file
View File

@ -0,0 +1,42 @@
package redis
import (
"fmt"
"git.loafle.net/overflow/overflow_gateway_app/conf"
"git.loafle.net/commons_go/logging"
crp "git.loafle.net/commons_go/redis_pool"
"github.com/garyburd/redigo/redis"
)
var RedisPool crp.Pool
func ExternalInit() {
ph := &redisPoolHandlers{}
ph.MaxCapacity = conf.Config.Redis.Pool.MaxCapacity
ph.MaxIdle = conf.Config.Redis.Pool.MaxIdle
ph.IdleTimeout = conf.Config.Redis.Pool.IdleTimeout
ph.Wait = conf.Config.Redis.Pool.Wait
RedisPool = crp.New(ph)
if err := RedisPool.Start(); nil != err {
logging.Logger().Panic(fmt.Sprintf("App: %v", err))
return
}
}
func ExternalDestroy() {
if nil != RedisPool {
RedisPool.Stop()
}
}
type redisPoolHandlers struct {
crp.PoolHandlers
}
func (ph *redisPoolHandlers) Dial() (redis.Conn, error) {
return redis.Dial(conf.Config.Redis.Network, conf.Config.Redis.Addr)
}

18
glide.yaml Normal file
View File

@ -0,0 +1,18 @@
package: git.loafle.net/overflow/overflow_gateway_app
import:
- package: git.loafle.net/commons_go/websocket_fasthttp
- package: git.loafle.net/commons_go/rpc
- package: git.loafle.net/commons_go/config
- package: git.loafle.net/overflow/overflow_gateway_config
- package: git.loafle.net/commons_go/logging
- package: git.loafle.net/commons_go/grpc_pool
- package: git.loafle.net/overflow/overflow_api_server
subpackages:
- golang
- package: git.loafle.net/commons_go/redis_pool
- package: github.com/garyburd/redigo
version: v1.3.0
subpackages:
- redis
- package: google.golang.org/grpc
version: v1.7.2

55
main.go Normal file
View File

@ -0,0 +1,55 @@
package main
import (
"flag"
"fmt"
"log"
"os"
"os/signal"
"syscall"
"git.loafle.net/commons_go/config"
"git.loafle.net/commons_go/logging"
"git.loafle.net/overflow/overflow_gateway_app/conf"
"git.loafle.net/overflow/overflow_gateway_app/external"
"git.loafle.net/overflow/overflow_gateway_app/server"
)
func init() {
configPath := flag.String("config", "./", "The path of config file")
flag.Parse()
config.SetConfigPath(*configPath)
if err := config.Load(&conf.Config, "config.json"); nil != err {
panic(err)
}
}
func main() {
defer logging.Logger().Sync()
external.ExternalInit()
s := server.New()
stop := make(chan os.Signal)
signal.Notify(stop, syscall.SIGINT)
go func() {
if err := s.Start(); nil != err {
log.Printf("Server: Start error %v", err)
return
}
}()
select {
case signal := <-stop:
fmt.Printf("Got signal: %v\n", signal)
}
external.ExternalDestroy()
s.Stop()
}

17
server/server.go Normal file
View File

@ -0,0 +1,17 @@
package server
import (
cwf "git.loafle.net/commons_go/websocket_fasthttp"
"git.loafle.net/overflow/overflow_gateway_app/servlet/web"
)
func New() cwf.Server {
sh := newServerHandler()
wsh := web.NewSocketHandler()
sh.RegisterSocketHandler("/web", wsh)
s := cwf.New(sh)
return s
}

45
server/server_handlers.go Normal file
View File

@ -0,0 +1,45 @@
package server
import (
"net"
cwf "git.loafle.net/commons_go/websocket_fasthttp"
"github.com/valyala/fasthttp"
)
func newServerHandler() cwf.ServerHandler {
sh := &ServerHandlers{}
return sh
}
type ServerHandlers struct {
cwf.ServerHandlers
}
func (sh *ServerHandlers) Listen() (net.Listener, error) {
return net.Listen("tcp4", ":19090")
}
func (sh *ServerHandlers) CheckOrigin(ctx *fasthttp.RequestCtx) bool {
if origin := string(ctx.Request.Header.Peek("Origin")); origin != "" {
ctx.Response.Header.Set("Access-Control-Allow-Origin", origin)
if string(ctx.Method()) == "OPTIONS" && string(ctx.Request.Header.Peek("Access-Control-Request-Method")) != "" {
ctx.Response.Header.Set("Access-Control-Allow-Headers", "Content-Type, Accept")
ctx.Response.Header.Set("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE")
}
}
return true
}
func (sh *ServerHandlers) OnError(ctx *fasthttp.RequestCtx, status int, reason error) {
// no op
}
func (sh *ServerHandlers) OnStart() {
// no op
}
func (sh *ServerHandlers) OnStop() {
// no op
}

View File

@ -0,0 +1,45 @@
package web
import (
"context"
"git.loafle.net/commons_go/rpc/gateway"
"git.loafle.net/commons_go/rpc/protocol/json"
cwf "git.loafle.net/commons_go/websocket_fasthttp"
"git.loafle.net/overflow/overflow_gateway_app/external/grpc"
"google.golang.org/grpc/metadata"
)
func newRCPServerHandler() gateway.ServerHandler {
sh := &RPCServerHandlers{}
sh.RegisterCodec(json.NewServerCodec(), "json")
return sh
}
type RPCServerHandlers struct {
gateway.ServerHandlers
}
func (rpcSH *RPCServerHandlers) Invoke(ctx context.Context, method string, params []string) (result interface{}, err error) {
soc := ctx.Value("socket").(*cwf.Socket)
md := metadata.Pairs("email", soc.ID().(string))
grpcCTX := metadata.NewOutgoingContext(context.Background(), md)
r, err := grpc.Exec(grpcCTX, method, params)
if err != nil {
return nil, err
}
return r, nil
}
func (rpcSH *RPCServerHandlers) Validate() {
rpcSH.ServerHandlers.Validate()
}
type Result struct {
Name string `json:"name,omitempty"`
Count int `json:"count,omitempty"`
}

View File

@ -0,0 +1,84 @@
package web
import (
"context"
"log"
"git.loafle.net/commons_go/rpc/gateway"
"git.loafle.net/commons_go/server"
cwf "git.loafle.net/commons_go/websocket_fasthttp"
"github.com/valyala/fasthttp"
)
func NewSocketHandler() cwf.SocketHandler {
sh := &SocketHandlers{}
sh.rpcServerHandler = newRCPServerHandler()
return sh
}
type SocketHandlers struct {
cwf.SocketHandlers
rpcServerHandler gateway.ServerHandler
}
func (sh *SocketHandlers) Handshake(ctx *fasthttp.RequestCtx) (interface{}, *fasthttp.ResponseHeader) {
return "overflow@loafle.com", nil
}
func (sh *SocketHandlers) Handle(soc *cwf.Socket, stopChan <-chan struct{}, doneChan chan<- struct{}) {
contentType := "json"
codec, err := sh.rpcServerHandler.GetCodec(contentType)
if nil != err {
log.Printf("RPC Handle: %v", err)
doneChan <- struct{}{}
return
}
var socConn *cwf.SocketConn
baseCtx := context.Background()
// conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
for {
if socConn, err = soc.WaitRequest(); nil != err {
doneChan <- struct{}{}
return
}
// // "git.loafle.net/commons_go/websocket_fasthttp/websocket"
// switch socConn.MessageType {
// case websocket.TextMessage:
// case websocket.BinaryMessage:
// }
ctx := context.WithValue(baseCtx, "socket", soc)
if err = gateway.Handle(ctx, sh.rpcServerHandler, codec, socConn, socConn); nil != err {
if server.IsClientDisconnect(err) {
doneChan <- struct{}{}
return
}
log.Printf("RPC: %v", err)
}
if err = socConn.Close(); nil != err {
doneChan <- struct{}{}
return
}
select {
case <-stopChan:
return
default:
}
}
}
func (sh *SocketHandlers) Validate() {
sh.SocketHandlers.Validate()
if nil == sh.rpcServerHandler {
panic("RPCServerHandler must be specified.")
}
}