Nginx做代理的一次实践

来源:互联网 发布:程序员会几种语言 编辑:程序博客网 时间:2024/05/16 10:30

背景

所在项目Go服务之前部署在测试机器上,最近再把Go的配置迁移到etcd,但是因为etcd没有对应的测试环境,而公司里面网段是隔离的,导致了原本的Go服务再接入etcd之后跑不起来。

  • 让Go服务正常启动,
  • 其他依赖方,比如前端、网关少做修改

方案

Go服务部署到docker上,docker上的域名都是特定后缀结尾,这样会涉及到cookie等一些问题,所以考虑通过测试机的Nginx做代理。

问题

  • http 426 报错:测试环境的http协议是1.0,而docker上的http协议是1.1,所以需要在nginx转发的时候,添加header头。如果是websocket可以参考下 https://www.nginx.com/blog/websocket-nginx/
  • http 404 报错:Nginx在做转发的时候,需要加上host header头,域名解析找到对应的主机,但是需要根据host信息,找到对应的服务。

插曲

再解决问题的时候,通过curl -I 在访问docker上的服务,一直提示404,但是通过curl直接访问的时候,正常。后来想到curl -I是通过head的方式请求。项目注册的路由请求方式是get,但是Iris的底层路由,404和405报错不能共存,iris默认会将404和405报错统一的转换成404报错。
直接上代码

pool.Run(w, r, func(context *iris.Context) {            routePath := context.Path()            for i := range mux.garden {                tree := mux.garden[i]                if !mux.methodEqual(context.Request.Method, tree.method) {                    continue                }                if mux.hosts && tree.subdomain != "" {                    requestHost := context.Host()                    // println("mux are true and tree.subdomain= " + tree.subdomain + "and hostname = " + hostname + " host = " + requestHost)                    if requestHost != hostname {                        // we have a subdomain                        if strings.Contains(tree.subdomain, iris.DynamicSubdomainIndicator) {                        } else {                            if tree.subdomain+hostname != requestHost {                                // go to the next tree, we have a subdomain but it is not the correct                                continue                            }                        }                    } else {                        //("it's subdomain but the request is not the same as the vhost)                        continue                    }                }                mustRedirect := tree.entry.getValue(routePath, context) // pass the parameters here for 0 allocation                if context.Middleware != nil {                    // ok we found the correct route, serve it and exit entirely from here                    //ctx.Request.Header.SetUserAgentBytes(DefaultUserAgent)                    context.Do()                    return                } else if mustRedirect && !context.Framework().Config.DisablePathCorrection { // && context.Method() == MethodConnect {                    reqPath := routePath                    pathLen := len(reqPath)                    if pathLen > 1 {                        if reqPath[pathLen-1] == '/' {                            reqPath = reqPath[:pathLen-1] //remove the last /                        } else {                            //it has path prefix, it doesn't ends with / and it hasn't be found, then just add the slash                            reqPath = reqPath + "/"                        }                        urlToRedirect := reqPath                        statusForRedirect := iris.StatusMovedPermanently // StatusMovedPermanently, this document is obselte, clients caches this.                        if tree.method == iris.MethodPost ||                            tree.method == iris.MethodPut ||                            tree.method == iris.MethodDelete {                            statusForRedirect = iris.StatusTemporaryRedirect // To maintain POST data                        }                        context.Redirect(urlToRedirect, statusForRedirect)                        // RFC2616 recommends that a short note "SHOULD" be included in the                        // response because older user agents may not understand 301/307.                        // Shouldn't send the response for POST or HEAD; that leaves GET.                        if tree.method == iris.MethodGet {                            note := "<a href=\"" + HTMLEscape(urlToRedirect) + "\">Moved Permanently</a>.\n"                            // ignore error                            context.WriteString(note)                        }                        return                    }                }                // not found                break            }            // https://github.com/kataras/iris/issues/469            if context.Framework().Config.FireMethodNotAllowed {                var methodAllowed string                for i := range mux.garden {                    tree := mux.garden[i]                    methodAllowed = tree.method // keep track of the allowed method of the last checked tree                    if !mux.methodEqual(context.Method(), tree.method) {                        continue                    }                }                // RCF rfc2616 https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html                // The response MUST include an Allow header containing a list of valid methods for the requested resource.                context.SetHeader("Allow", methodAllowed)                context.EmitError(iris.StatusMethodNotAllowed)                return            }            context.EmitError(iris.StatusNotFound)        })
原创粉丝点击