chore: 并入 iotlcm-upstream-proxy 历史到 upstream-proxy/(原提交 44209ec)
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/controller/infopb"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/controller/msgcallpb"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/service"
|
||||
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubconsts"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/pub/xjpubservice"
|
||||
"github.com/gogf/gf/contrib/rpc/grpcx/v2"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/gsvc"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/reflection"
|
||||
)
|
||||
|
||||
const (
|
||||
ServiceNamePrefix = "iotlcmupstreamproxy"
|
||||
)
|
||||
|
||||
var (
|
||||
gGrpcPort = 8700
|
||||
gAccessIP = "0.0.0.0"
|
||||
)
|
||||
var (
|
||||
Main = gcmd.Command{
|
||||
Name: "main",
|
||||
Usage: "main",
|
||||
Brief: "start http server",
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
s := g.Server()
|
||||
gGrpcPort = gconv.Int(gcmd.GetOptWithEnv("grpcport"))
|
||||
gAccessIP = gconv.String(gcmd.GetOptWithEnv("accessip"))
|
||||
|
||||
if len(gAccessIP) == 0 {
|
||||
gAccessIP = "0.0.0.0"
|
||||
}
|
||||
if gGrpcPort == 0 {
|
||||
gGrpcPort = 8110
|
||||
}
|
||||
nodeName := fmt.Sprintf("%s", ServiceNamePrefix)
|
||||
|
||||
xjpubservice.Info().SetInfoName(xjpubconsts.ServiceTypeAccess, fmt.Sprintf("%s-http-svc", ServiceNamePrefix), "上游运营商渠道服务", "上游运营商渠道服务")
|
||||
xjpubservice.Info().AddInfoData("grpcport", gGrpcPort)
|
||||
xjpubservice.Info().AddInfoData("accessip", gAccessIP)
|
||||
xjpubservice.Info().AddInfoData("nodeName", nodeName)
|
||||
|
||||
xjpubservice.InfoRpc().SetInfoName(xjpubconsts.ServiceTypeAccess, fmt.Sprintf("%s-grpc-svc", ServiceNamePrefix), "上游运营商渠道服务", "上游运营商渠道服务")
|
||||
xjpubservice.InfoRpc().AddInfoData("grpcport", gGrpcPort)
|
||||
xjpubservice.InfoRpc().AddInfoData("accessip", gAccessIP)
|
||||
xjpubservice.InfoRpc().AddInfoData("nodeName", nodeName)
|
||||
bindHTTPRoutes(s)
|
||||
err = service.ChannelConfig().Start(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = service.UpstreamAPI().Start(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
c := grpcx.Server.NewConfig()
|
||||
c.Endpoints = []string{fmt.Sprintf("%s:%d", gAccessIP, gGrpcPort)}
|
||||
c.Options = append(c.Options, []grpc.ServerOption{
|
||||
grpcx.Server.ChainUnary(
|
||||
grpcx.Server.UnaryValidate,
|
||||
),
|
||||
}...)
|
||||
sGRPC := grpcx.Server.New(c)
|
||||
sGRPC.Service(&gsvc.LocalService{
|
||||
Name: fmt.Sprintf("%s-grpc-svc", ServiceNamePrefix),
|
||||
Endpoints: gsvc.Endpoints{gsvc.NewEndpoint(fmt.Sprintf("%s:%d", gAccessIP, gGrpcPort))},
|
||||
Metadata: gsvc.Metadata{
|
||||
gsvc.MDProtocol: "grpc",
|
||||
gsvc.MDInsecure: true,
|
||||
},
|
||||
})
|
||||
infopb.Register(sGRPC)
|
||||
msgcallpb.Register(sGRPC)
|
||||
reflection.Register(sGRPC.Server)
|
||||
g.Log().Infof(ctx, "GRPC Server启动, listenPort:%d", gGrpcPort)
|
||||
sGRPC.Run()
|
||||
g.Log().Infof(ctx, "GRPC Server堵塞运行结束")
|
||||
}()
|
||||
|
||||
s.Run()
|
||||
service.UpstreamAPI().Stop(ctx)
|
||||
service.ChannelConfig().Stop(ctx)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,19 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/controller/cardquery"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/controller/channel"
|
||||
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
func bindHTTPRoutes(server *ghttp.Server) {
|
||||
server.Group("/", func(group *ghttp.RouterGroup) {
|
||||
group.Middleware(ghttp.MiddlewareHandlerResponse)
|
||||
group.Bind(
|
||||
cardquery.NewV1(),
|
||||
channel.NewV1(),
|
||||
)
|
||||
group.POST("/internal/app-diagnosis/sim/*any", cardquery.AppDiagnosisQuery)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gcfg"
|
||||
v1 "git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/api/cardquery/v1"
|
||||
_ "git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/logic/simKeyFill"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/logic/upstreamapi"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/logic/upstreamimpl"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/model"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/service"
|
||||
)
|
||||
|
||||
func TestAPNHTTPHarness(t *testing.T) {
|
||||
if os.Getenv("APN_HTTP_CHAIN_HELPER") != "1" {
|
||||
t.Skip("未启用本机HTTP模拟链")
|
||||
}
|
||||
gateway, err := url.Parse(os.Getenv("APN_HTTP_CHAIN_CHAN"))
|
||||
if err != nil || gateway.Scheme != "http" || gateway.Hostname() != "127.0.0.1" || gateway.Port() == "" {
|
||||
t.Fatal("只允许本机模拟chan")
|
||||
}
|
||||
adapter, err := gcfg.NewAdapterContent(fmt.Sprintf(`{"gateway":{"address":%q,"timeout":"2s"}}`, gateway.Host))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
g.Cfg().SetAdapter(adapter)
|
||||
api := upstreamapi.NewUpstreamAPI()
|
||||
api.RegisterChan("fake-channel", "1", &model.SimCardChannelCache{Instance: upstreamimpl.NewSimYD()})
|
||||
service.RegisterUpstreamAPI(api)
|
||||
server := ghttp.GetServer(t.Name())
|
||||
server.SetAddr("127.0.0.1:0")
|
||||
bindHTTPRoutes(server)
|
||||
stop := make(chan struct{})
|
||||
server.BindHandler("POST:/__test/stop", func(r *ghttp.Request) { close(stop) })
|
||||
if err := server.Start(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer server.Shutdown()
|
||||
fmt.Printf("APN_CHAIN_READY=http://127.0.0.1:%d\n", server.GetListenedPort())
|
||||
select {
|
||||
case <-stop:
|
||||
case <-time.After(3 * time.Minute):
|
||||
t.Error("HTTP模拟链未正常结束")
|
||||
}
|
||||
}
|
||||
|
||||
type apnBindingTestFill struct {
|
||||
service.ISimKeyFill
|
||||
captured chan model.SimBaseReqJson
|
||||
}
|
||||
|
||||
func (s *apnBindingTestFill) SimKeyFill(_ context.Context, input *model.SimBaseReqJson) (model.SimBaseResJson, error) {
|
||||
s.captured <- *input
|
||||
return model.SimBaseResJson{}, nil
|
||||
}
|
||||
|
||||
func TestAPNProductionHTTPBindingPreservesRawPayload(t *testing.T) {
|
||||
old := service.SimKeyFill()
|
||||
capture := &apnBindingTestFill{ISimKeyFill: old, captured: make(chan model.SimBaseReqJson, 1)}
|
||||
service.RegisterSimKeyFill(capture)
|
||||
t.Cleanup(func() { service.RegisterSimKeyFill(old) })
|
||||
server := ghttp.GetServer(t.Name())
|
||||
server.SetAddr("127.0.0.1:0")
|
||||
bindHTTPRoutes(server)
|
||||
server.BindHandler("POST:/__test/legacy-binding", func(r *ghttp.Request) {
|
||||
var req v1.SimBaseReq
|
||||
if err := r.Parse(&req); err != nil {
|
||||
t.Error(err)
|
||||
r.Response.WriteStatus(400)
|
||||
return
|
||||
}
|
||||
capture.captured <- req.SimBaseReqJson
|
||||
})
|
||||
if err := server.Start(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = server.Shutdown() })
|
||||
for _, data := range []string{
|
||||
`{"operationId":"frozen-operation","submitOnly":true,"operType":"1","apnName":"CMIOT"}`,
|
||||
`{"operationId":"frozen-operation","queryJobId":"saved-job","operType":"1","apnName":"CMIOT"}`,
|
||||
`{"operationId":"frozen-operation","recoverOnly":true,"operType":"1","apnName":"CMIOT"}`,
|
||||
} {
|
||||
for _, path := range []string{"/sim/change/sim-apn", "/sim/query/sim-apn-capability", "/sim/query/sim-session"} {
|
||||
input := model.SimBaseReqJson{SimKeys: []*model.SimKey{{ChanKey: "fake", ICCID: "fake-card", MSISDN: "frozen-number"}}, ReqData: json.RawMessage(data)}
|
||||
response, err := g.Client().ContentJson().Post(context.Background(), fmt.Sprintf("http://127.0.0.1:%d%s", server.GetListenedPort(), path), input)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
body := response.ReadAll()
|
||||
_ = response.Close()
|
||||
select {
|
||||
case got := <-capture.captured:
|
||||
var wantData, gotData map[string]any
|
||||
_ = json.Unmarshal(input.ReqData, &wantData)
|
||||
_ = json.Unmarshal(got.ReqData, &gotData)
|
||||
wantJSON, _ := json.Marshal(wantData)
|
||||
gotJSON, _ := json.Marshal(gotData)
|
||||
if path == "/sim/query/sim-session" {
|
||||
baselineResponse, err := g.Client().ContentJson().Post(context.Background(), fmt.Sprintf("http://127.0.0.1:%d/__test/legacy-binding", server.GetListenedPort()), input)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = baselineResponse.Close()
|
||||
baseline := <-capture.captured
|
||||
if string(got.ReqData) != string(baseline.ReqData) {
|
||||
t.Fatalf("非APN旧绑定行为改变:got=%q baseline=%q", got.ReqData, baseline.ReqData)
|
||||
}
|
||||
} else if sha256.Sum256(wantJSON) != sha256.Sum256(gotJSON) {
|
||||
t.Fatalf("APN冻结请求摘要改变:path=%s want=%s got=%s", path, wantJSON, gotJSON)
|
||||
}
|
||||
if len(got.SimKeys) != 1 || *got.SimKeys[0] != *input.SimKeys[0] {
|
||||
t.Fatalf("代理生产绑定丢字段:%+v", got)
|
||||
}
|
||||
default:
|
||||
t.Fatalf("未经过生产代理controller:%s", body)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBindHTTPRoutesRegistersChannelControlRoutes(t *testing.T) {
|
||||
server := ghttp.GetServer("proxy-channel-refresh-route-test")
|
||||
server.SetAddr("127.0.0.1:0")
|
||||
bindHTTPRoutes(server)
|
||||
if err := server.Start(); err != nil {
|
||||
t.Fatalf("start HTTP server: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if err := server.Shutdown(); err != nil {
|
||||
t.Errorf("shutdown HTTP server: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
want := map[string]bool{
|
||||
"/internal/channel/refresh": false,
|
||||
"/internal/channel/remove": false,
|
||||
"/internal/app-diagnosis/sim/*any": false,
|
||||
}
|
||||
for _, route := range server.GetRoutes() {
|
||||
if _, ok := want[route.Route]; ok && strings.EqualFold(route.Method, "POST") {
|
||||
want[route.Route] = true
|
||||
}
|
||||
}
|
||||
for route, found := range want {
|
||||
if !found {
|
||||
t.Fatalf("POST %s route was not registered: %+v", route, server.GetRoutes())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user