我正在尝试使用Nginx封装由我们的一位客户托管的,记录不佳且气质性很差的API。尽管我尽了最大的努力,但我还是无法让Nginx将我们要发出的请求(带有两个参数作为URL参数的GET请求)的入站格式转换成我们需要提交给此API的内容(带有POST请求的一个将参数编码为JSON Blob的请求正文。
我可以用Python代码对该API进行有效调用,但是我无法弄清楚在Nginx设置中我无法做的事情来复制行为。这里的想法是将请求从慢速Python代码包装到Nginx。
Python代码如下所示:
REMOTE_URI = 'https://api.mycompany.com/services/some/api/endpoint/here/'
async def get_promotion_data(customer_id, product_id):
params = {'AccountNumber': customer_id,
'ProductIdentifier': product_id}
async with aiohttp.ClientSession() as session:
async with session.post(REMOTE_URI,
headers={'Content-Type': 'application/json'},
data=json.dumps(params)) as response:
data = await response.json()
if not data:
return {}
return data
要使它在Nginx中正常运行,我的最佳尝试是:
location /internal/wrapper {
proxy_set_header Host api.mycompany.com;
proxy_set_header Connection "";
proxy_connect_timeout 100ms;
proxy_read_timeout 5s;
proxy_method POST;
proxy_set_body '{"AccountNumber":"${arg_customer_id}","ProductIdentifier":"${arg_product_id}"}';
proxy_set_header X-Content-Type application/json;
proxy_pass https://api.mycompany.com/services/some/api/endpoint/here/;
}
但是,当我调用Nginx包装版本时,它总是返回504,即与上游的连接超时。 (我已经尝试增加Nginx中的代理超时;我们连接到的API速度很快,所以几乎绝对不是问题。)
通过使用我们直接使用curl
之类的工具来调用API的最大猜测是,客户端的某些内容是根据URL中的主机名进行路由的。当我尝试执行curl "https://api.mycompany.com/services/some/api/endpoint/here/"
时,它会返回一条响应,表明我在选择正确的服务器。当我做curl "https://123.123.123.123/services/some/api/endpoint/here/"
时,会得到一堆重定向。
似乎Nginx正在解析域并直接调用IP,而不是显式传递主机名。在error.log
文件中,它记录了它尝试(并对其超时)的上游是123.123.123.123
而不是api.mycompany.com
。这也是为什么我尝试添加Host
标头作为代理通过的一部分。
也许我还想念其他东西吗?代理时还有其他方法告诉Nginx如何处理主机名吗?
答案 0 :(得分:0)
事实证明这里有两个错误。首先,JSON内容类型的标头是Content-Type
而不是X-Content-Type
。更重要的是,我需要向配置中添加proxy_ssl_server_name on
。原来我对主机名是一个问题是正确的,真正的问题是由于Nginx在发出HTTP请求时未发送服务器名。