blob: 4b87123df1211143c5d00465cccc899236806820 [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 (
"context"
"encoding/json"
"math"
"net"
"net/http"
"net/url"
"strings"
"time"
)
import (
"github.com/dubbo-go-pixiu/pixiu-api/pkg/router"
)
import (
"github.com/apache/dubbo-go-pixiu/pkg/client"
"github.com/apache/dubbo-go-pixiu/pkg/common/constant"
"github.com/apache/dubbo-go-pixiu/pkg/logger"
"github.com/apache/dubbo-go-pixiu/pkg/model"
)
const abortIndex int8 = math.MaxInt8 / 2
// HttpContext http context
type HttpContext struct {
//Deprecated: waiting to delete
Index int8
//Deprecated: waiting to delete
Filters FilterChain
Timeout time.Duration
Ctx context.Context
Params map[string]interface{}
// localReply Means that the request was interrupted,
// which may occur in the Decode or Encode stage
localReply bool
// statusCode code will be return
statusCode int
// localReplyBody: happen error
localReplyBody []byte
// the response context will return.
TargetResp *client.Response
// client call response.
SourceResp interface{}
HttpConnectionManager model.HttpConnectionManagerConfig
Route *model.RouteAction
Api *router.API
Request *http.Request
Writer http.ResponseWriter
}
type (
// ErrResponse err response.
ErrResponse struct {
Message string `json:"message"`
}
// FilterFunc filter func, filter
FilterFunc func(c *HttpContext)
// FilterChain filter chain
FilterChain []FilterFunc
)
// Deprecated: Next logic for lookup filter
func (hc *HttpContext) Next() {
}
// Reset reset http context
func (hc *HttpContext) Reset() {
hc.Ctx = nil
hc.Index = -1
hc.Filters = []FilterFunc{}
hc.Route = nil
hc.Api = nil
hc.TargetResp = nil
hc.SourceResp = nil
hc.statusCode = 0
hc.localReply = false
hc.localReplyBody = nil
}
// RouteEntry set route
func (hc *HttpContext) RouteEntry(r *model.RouteAction) {
hc.Route = r
}
// GetRouteEntry get route
func (hc *HttpContext) GetRouteEntry() *model.RouteAction {
return hc.Route
}
// AddHeader add header
func (hc *HttpContext) AddHeader(k, v string) {
hc.Writer.Header().Add(k, v)
}
// GetHeader get header
func (hc *HttpContext) GetHeader(k string) string {
return hc.Request.Header.Get(k)
}
// AllHeaders get all headers
func (hc *HttpContext) AllHeaders() http.Header {
return hc.Request.Header
}
// GetUrl get http request url
func (hc *HttpContext) GetUrl() string {
return hc.Request.URL.Path
}
func (hc *HttpContext) SetUrl(url string) {
hc.Request.URL.Path = url
}
// GetMethod get method, POST/GET ...
func (hc *HttpContext) GetMethod() string {
return hc.Request.Method
}
// GetClientIP get client IP
func (hc *HttpContext) GetClientIP() string {
xForwardedFor := hc.Request.Header.Get("X-Forwarded-For")
ip := strings.TrimSpace(strings.Split(xForwardedFor, ",")[0])
if len(ip) != 0 {
return ip
}
ip = strings.TrimSpace(hc.Request.Header.Get("X-Real-Ip"))
if len(ip) != 0 {
return ip
}
if ip, _, err := net.SplitHostPort(strings.TrimSpace(hc.Request.RemoteAddr)); err == nil && len(ip) != 0 {
return ip
}
return ""
}
// GetApplicationName get application name
func (hc *HttpContext) GetApplicationName() string {
if u, err := url.Parse(hc.Request.RequestURI); err == nil {
return strings.Split(u.Path, "/")[0]
}
return ""
}
// SendLocalReply Means that the request was interrupted and Response will be sent directly
// Even if it’s currently in to Decode stage
func (hc *HttpContext) SendLocalReply(status int, body []byte) {
hc.localReply = true
hc.statusCode = status
hc.localReplyBody = body
hc.TargetResp = &client.Response{Data: body}
if json.Valid(body) {
hc.AddHeader(constant.HeaderKeyContextType, constant.HeaderValueApplicationJson)
} else {
hc.AddHeader(constant.HeaderKeyContextType, constant.HeaderValueTextPlain)
}
writer := hc.Writer
writer.WriteHeader(status)
_, err := writer.Write(body)
if err != nil {
logger.Errorf("write fail: %v", err)
}
}
func (hc *HttpContext) GetLocalReplyBody() []byte {
return hc.localReplyBody
}
func (hc *HttpContext) GetStatusCode() int {
return hc.statusCode
}
func (hc *HttpContext) StatusCode(code int) {
hc.statusCode = code
}
func (hc *HttpContext) LocalReply() bool {
return hc.localReply
}
// API sets the API to http context
func (hc *HttpContext) API(api router.API) {
hc.Timeout = api.Timeout
hc.Api = &api
}
// GetAPI get api
func (hc *HttpContext) GetAPI() *router.API {
return hc.Api
}
// Deprecated: Abort filter chain break , filter after the current filter will not executed.
func (hc *HttpContext) Abort() {
hc.Index = abortIndex
}
// Deprecated: AppendFilterFunc append filter func.
func (hc *HttpContext) AppendFilterFunc(ff ...FilterFunc) {
for _, v := range ff {
hc.Filters = append(hc.Filters, v)
}
}