Nginx做代理的一次实践

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/w15249243295/article/details/78763974

背景

所在项目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)
        })

猜你喜欢

转载自blog.csdn.net/w15249243295/article/details/78763974