blob: fcd7988638bd57f04ccb54b01d87bbfc2dba2315 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package http
import (
"github.com/apache/servicecomb-mesher/proxy/common"
"github.com/apache/servicecomb-mesher/proxy/ingress"
"github.com/go-chassis/go-chassis/v2/client/rest"
chassiscommon "github.com/go-chassis/go-chassis/v2/core/common"
"github.com/go-chassis/go-chassis/v2/core/handler"
"github.com/go-chassis/go-chassis/v2/core/invocation"
"github.com/go-chassis/openlog"
"net/http"
)
func handleIncomingTraffic(inv *invocation.Invocation) (*invocation.Response, error) {
c, err := handler.GetChain(chassiscommon.Provider, common.ChainProviderIncoming)
if err != nil {
openlog.Error("Get chain failed: " + err.Error())
return nil, err
}
var invRsp *invocation.Response
c.Next(inv, func(ir *invocation.Response) {
invRsp = ir
})
return invRsp, nil
}
//HandleIngressTraffic is api gateway http handler
func HandleIngressTraffic(w http.ResponseWriter, r *http.Request) {
inv := &invocation.Invocation{}
inv.Reply = rest.NewResponse()
inv.Protocol = "rest"
inv.Args = r
h := make(map[string]string)
for k := range r.Header {
h[k] = r.Header.Get(k)
}
inv.Ctx = chassiscommon.NewContext(h)
invResp, err := handleIncomingTraffic(inv)
if err != nil {
handleErrorResponse(inv, w, http.StatusInternalServerError, err)
return
}
if invResp != nil {
if invResp.Status != 0 || invResp.Err != nil {
handleErrorResponse(inv, w, invResp.Status, invResp.Err)
return
}
}
rule, err := ingress.DefaultFetcher.Fetch("http", r.Host, r.URL.Path, r.Header)
if err != nil {
handleErrorResponse(inv, w, http.StatusInternalServerError, err)
return
}
inv.MicroServiceName = rule.Service.Name
targetAPI := r.URL.Path
if rule.Service.RedirectPath != "" {
targetAPI = rule.Service.RedirectPath
}
newReq, err := http.NewRequest(r.Method, "http://"+inv.MicroServiceName+targetAPI, r.Body)
if err != nil {
handleErrorResponse(inv, w, http.StatusInternalServerError, err)
return
}
inv.Args = newReq
h[XForwardedPort] = rule.Service.Port.Value
c, err := handler.GetChain(chassiscommon.Consumer, common.ChainConsumerOutgoing)
if err != nil {
handleErrorResponse(inv, w, http.StatusBadGateway, err)
openlog.Error("Get chain failed: " + err.Error())
return
}
var invRsp *invocation.Response
c.Next(inv, func(ir *invocation.Response) {
//Send the request to the destination
invRsp = ir
})
resp, err := handleRequest(w, inv, invRsp)
if err != nil {
openlog.Error("Handle request failed: " + err.Error())
return
}
RecordStatus(inv, resp.StatusCode)
}