注意:我已经改变了这个问题,试图让它更多地指出问题所在.以下评论不再反映这一问题.
我想从fbcdn获取这个图像:
浏览器得到它就好了.这是我的代码:
public class ReverseProxyController : NancyModule { public ReverseProxyController() { Get["/",true] = async (parameters,ct) => { var result = await GetResult(parameters,ct); return result; }; } private async Task<Response> GetResult(dynamic parameters,CancellationToken ct) { var client = new HttpClient(); string url = Request.Query["url"].Value.ToString(); if (url == null) return null; client.DefaultRequestHeaders.Add("Access-Control-Allow-Origin","*"); client.DefaultRequestHeaders.Add("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/54.0.2840.71 Safari/537.36"); client.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests","1"); client.DefaultRequestHeaders.Add("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); client.DefaultRequestHeaders.Add("Accept-Encoding","gzip,deflate,sdch,br"); client.DefaultRequestHeaders.Add("Accept-Language","en-US,en;q=0.8,ru;q=0.6"); var response = await client.GetAsync(url,ct); ct.ThrowIfCancellationRequested(); switch (response.StatusCode) { case HttpStatusCode.OK: var stream = await response.Content.ReadAsStreamAsync(); return Response.FromStream(stream,response.Content.Headers.ContentType != null ? response.Content.Headers.ContentType.ToString() : "application/octet-stream"); default: return Response.AsText("\nError " + response.StatusCode); } } }
我每次都得到403 Forbidden响应.我认为添加标题会使它工作但不会去.
此代码适用于其他主机上的其他图像,如下所示:
https://s-media-cache-ak0.pinimg.com/564x/ff/f0/c9/fff0c988a4516659d4009f60e0694cb6.jpg
解决方法
问题出在Nancy请求的URL Retrieval中,而不是使用HttpClient获取数据.
我假设您正在向南希发送请求,例如:
因此对于Facebook,它将是:
但对于这个url字符串url = Request.Query [“url”].Value.ToString();是不完整的并且缺少最后一部分(& oe = 589AAD2F),因此服务器响应Forbidden.
以下是演示此问题的简单更改:
private async Task<Response> GetResult(dynamic parameters,CancellationToken ct) { var client = new HttpClient(); var req = Request.Url.ToString(); var queryStart = req.IndexOf("url="); if (queryStart == -1) return Nancy.HttpStatusCode.BadRequest; var url = req.Substring(queryStart + 4); if (string.IsNullOrEmpty(url)) return Nancy.HttpStatusCode.BadRequest; client.DefaultRequestHeaders.Add("Access-Control-Allow-Origin","*"); client.DefaultRequestHeaders.Add("User-Agent",like Gecko) Chrome/54.0.2840.71 Safari/537.36"); client.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests","1"); client.DefaultRequestHeaders.Add("Accept",*/*;q=0.8"); client.DefaultRequestHeaders.Add("Accept-Encoding",br"); client.DefaultRequestHeaders.Add("Accept-Language",ru;q=0.6"); var response = await client.GetAsync(url,ct); ct.ThrowIfCancellationRequested(); switch (response.StatusCode) { case System.Net.HttpStatusCode.OK: var stream = await response.Content.ReadAsStreamAsync(); return Response.FromStream(stream,response.Content.Headers.ContentType != null ? response.Content.Headers.ContentType.ToString() : "application/octet-stream"); default: return Response.AsText("\nError " + response.StatusCode); } }
解
我们实际上可以在发送之前对URL进行编码,Nancy将自动为我们解码URL,因此无需更改任何服务器端.
这是使用HttpUtility.UrlEncode生成的链接示例
结果:
https://scontent.xx.fbcdn.net/v/t1.0-1/c15.0.50.50/p50x50/10354686_10150004552801856_220367501106153455_n.jpg?oh=6c801f82cd5a32fd6e5a4258ce00a314\u0026oe=589AAD2F
并且对此特定链接的实际请求将是:
替代解决方案
在这种情况下我个人更喜欢POST而不是GET,所以这里是:
public class ReverseProxyController : NancyModule { class ProxyRequest { public string Url { get; set; } } public ReverseProxyController() { Post["/",CancellationToken ct) { var pReq = this.Bind<ProxyRequest>(); var url = pReq.Url; if (string.IsNullOrEmpty(url)) return null; var client = new HttpClient(); client.DefaultRequestHeaders.Add("Access-Control-Allow-Origin",ct); ct.ThrowIfCancellationRequested(); switch (response.StatusCode) { case System.Net.HttpStatusCode.OK: var stream = await response.Content.ReadAsStreamAsync(); return Response.FromStream(stream,response.Content.Headers.ContentType != null ? response.Content.Headers.ContentType.ToString() : "application/octet-stream"); default: return Response.AsText("\nError " + response.StatusCode); } } }