Browse Source

integrate restful api with v2 service

Shelikhoo 4 years ago
parent
commit
75a571a4ce

+ 18 - 0
app/restful-api/config.proto

@@ -0,0 +1,18 @@
+syntax = "proto3";
+
+package v2ray.app.restfulapi;
+option csharp_namespace = "V2Ray.App.Restapi";
+option go_package = "github.com/v2fly/v2ray-core/v4/app/restful-api;restful_api";
+option java_package = "com.v2ray.core.app.restapi";
+option java_multiple_files = true;
+
+import "common/protoext/extensions.proto";
+
+message Config{
+  option (v2ray.core.common.protoext.message_opt).type = "service";
+  option (v2ray.core.common.protoext.message_opt).short_name = "restful-api";
+
+  string listen_addr = 1;
+  int32 listen_port = 2;
+  string auth_token = 3;
+}

+ 28 - 5
app/restful-api/restful-api.go

@@ -2,7 +2,10 @@ package restful_api
 
 import (
 	"github.com/gin-gonic/gin"
+	"github.com/v2fly/v2ray-core/v4/common/net"
+	"github.com/v2fly/v2ray-core/v4/transport/internet"
 	"net/http"
+	"strings"
 )
 
 type StatsUser struct {
@@ -55,7 +58,7 @@ func stats(c *gin.Context) {
 	c.JSON(http.StatusOK, response)
 }
 
-func loggerReboot(c *gin.Context)  {
+func loggerReboot(c *gin.Context) {
 	c.JSON(http.StatusOK, gin.H{})
 }
 
@@ -71,8 +74,9 @@ func TokenAuthMiddleware() gin.HandlerFunc {
 	}
 }
 
-func Start() error {
-	r := gin.New()
+func (r *restfulService) start() error {
+	r.Engine = gin.New()
+
 	r.GET("/ping", func(c *gin.Context) {
 		c.JSON(200, gin.H{
 			"message": "pong",
@@ -87,9 +91,28 @@ func Start() error {
 		v1.POST("/logger/reboot", loggerReboot)
 	}
 
-	if err := r.Run(":3000"); err != nil {
-		return err
+	var listener net.Listener
+	var err error
+	address := net.ParseAddress(r.config.ListenAddr)
+
+	switch {
+	case address.Family().IsIP():
+		listener, err = internet.ListenSystem(r.ctx, &net.TCPAddr{IP: address.IP(), Port: int(r.config.ListenPort)}, nil)
+	case strings.EqualFold(address.Domain(), "localhost"):
+		listener, err = internet.ListenSystem(r.ctx, &net.TCPAddr{IP: net.IP{127, 0, 0, 1}, Port: int(r.config.ListenPort)}, nil)
+	default:
+		return newError("restful api cannot listen on the address: ", address)
+	}
+	if err != nil {
+		return newError("restful api cannot listen on the port ", r.config.ListenPort).Base(err)
 	}
 
+	r.listener = listener
+	go func() {
+		if err := r.RunListener(listener); err != nil {
+			newError("unable to serve restful api").WriteToLog()
+		}
+	}()
+
 	return nil
 }

+ 39 - 0
app/restful-api/service.go

@@ -0,0 +1,39 @@
+package restful_api
+
+import (
+	"context"
+	"github.com/gin-gonic/gin"
+	"net"
+	"sync"
+)
+
+//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
+
+type restfulService struct {
+	*gin.Engine
+
+	listener net.Listener
+	config   *Config
+	access   sync.Mutex
+
+	ctx context.Context
+}
+
+func (r *restfulService) Type() interface{} {
+	return (*struct{})(nil)
+}
+
+func (r *restfulService) Start() error {
+	defer r.access.Unlock()
+	r.access.Lock()
+	return r.start()
+}
+
+func (r *restfulService) Close() error {
+	defer r.access.Unlock()
+	r.access.Lock()
+	if r.listener != nil {
+		return r.listener.Close()
+	}
+	return nil
+}

+ 13 - 0
app/restful-api/service_test.go

@@ -0,0 +1,13 @@
+package restful_api
+
+import (
+	"github.com/stretchr/testify/assert"
+	"reflect"
+	"testing"
+)
+
+func TestTypeReturnAnonymousType(t *testing.T) {
+	service := restfulService{}
+	serviceType := service.Type()
+	assert.Empty(t, reflect.TypeOf(serviceType).Name(), "must return anonymous type")
+}