go-kitGolang
实现
API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。
用于实现API网关的技术有很多,大致分为这么几类:
NginxHaproxyNettyServletSpring Cloud GatewayZuulZuul2
net/http/httputilReverseProxyfunc NewSingleHostReverseProxy(target *url.URL) *ReverseProxytype ReverseProxy
func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy
// NewSingleHostReverseProxy returns a new ReverseProxy that routes
// URLs to the scheme, host, and base path provided in target. If the
// target's path is "/base" and the incoming request was for "/dir",
// the target request will be for /base/dir.
// NewSingleHostReverseProxy does not rewrite the Host header.
// To rewrite Host headers, use ReverseProxy directly with a custom
// Director policy.
func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
targetQuery := target.RawQuery
director := func(req *http.Request) {
req.URL.Scheme = target.Scheme
req.URL.Host = target.Host
req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
if targetQuery == "" || req.URL.RawQuery == "" {
req.URL.RawQuery = targetQuery + req.URL.RawQuery
} else {
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
}
if _, ok := req.Header["User-Agent"]; !ok {
// explicitly disable User-Agent so it's not set to default value
req.Header.Set("User-Agent", "")
}
}
return &ReverseProxy{Director: director}
}
NewSingleHostReverseProxyReverseProxyURLstargeschemehostbase path
// ReverseProxy is an HTTP Handler that takes an incoming request and
// sends it to another server, proxying the response back to the
// client.
type ReverseProxy struct {
// Director must be a function which modifies
// the request into a new request to be sent
// using Transport. Its response is then copied
// back to the original client unmodified.
// Director must not access the provided Request
// after returning.
Director func(*http.Request)
Transport http.RoundTripper
FlushInterval time.Duration
ErrorLog *log.Logger
BufferPool BufferPool
// ModifyResponse is an optional function that modifies the
// Response from the backend. It is called if the backend
// returns a response at all, with any HTTP status code.
// If the backend is unreachable, the optional ErrorHandler is
// called without any call to ModifyResponse.
//
// If ModifyResponse returns an error, ErrorHandler is called
// with its error value. If ErrorHandler is nil, its default
// implementation is used.
ModifyResponse func(*http.Response) error
ErrorHandler func(http.ResponseWriter, *http.Request, error)
}
ReverseProxyDirectorModifyResponseServeHTTPDirectorModifyResponse
NewSingleHostReverseProxyURLsDirectorNewSingleHostReverseProxy
代码
userauth
package main
import (
"fmt"
"log"
"net/http"
"net/http/httputil"
"net/url"
"strings"
)
type handle struct {
host string
port string
}
type Service struct {
auth *handle
user *handle
}
func (this *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var remote *url.URL
if strings.Contains(r.RequestURI, "api/auth") {
remote, _ = url.Parse("http://" + this.auth.host + ":" + this.auth.port)
} else if strings.Contains(r.RequestURI, "api/user") {
remote, _ = url.Parse("http://" + this.user.host + ":" + this.user.port)
} else {
fmt.Fprintf(w, "404 Not Found")
return
}
proxy := httputil.NewSingleHostReverseProxy(remote)
proxy.ServeHTTP(w, r)
}
func startServer() {
// 注册被代理的服务器 (host, port)
service := &Service{
auth: &handle{host: "127.0.0.1", port: "8081"},
user: &handle{host: "127.0.0.1", port: "8082"},
}
err := http.ListenAndServe(":8888", service)
if err != nil {
log.Fatalln("ListenAndServe: ", err)
}
}
func main() {
startServer()
}