2016-10-29 2 views
7

ПРИМЕЧАНИЕ. Я изменил этот вопрос совсем немного, пытаясь указать на проблему. Приведенные ниже комментарии больше не отражают этот вопрос.Async NancyFX с HttpClient - GetAsync для fbcdn возвращает 403 запрещено?

Я пытаюсь получить это изображение от fbcdn:

https://scontent.xx.fbcdn.net/v/t1.0-1/c15.0.50.50/p50x50/10354686_10150004552801856_220367501106153455_n.jpg?oh=6c801f82cd5a32fd6e5a4258ce00a314&oe=589AAD2F

браузер получает это просто отлично. Вот мой код:

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 каждый раз. Я думал, что добавление заголовков заставит его работать, но не пойдет.

Этот код работает для других изображений на других хостах, как этот:

https://s-media-cache-ak0.pinimg.com/564x/ff/f0/c9/fff0c988a4516659d4009f60e0694cb6.jpg

+0

Итак, 'Response.FromStream' и' Response.AsText', из чего это lib? Или что они делают? – Jim

+0

хорошо, если это не может быть и речи, если я проверяю другой код, отлично работает здесь с 200 ответами – Jim

+0

Действительно? С URL-адресом fbcdn? – richard

ответ

3

Проблема заключается в URL Retrieval из запроса Нэнси, не получая данные с HttpClient.

I Предположим, вы отправляете запрос на Nancy как:

http://localhost/?url= ...

, следовательно, для Facebook, это было бы:

http://localhost/?url=https://scontent.xx.fbcdn.net/v/t1.0-1/c15.0.50.50/p50x50/10354686_10150004552801856_220367501106153455_n.jpg?oh=6c801f82cd5a32fd6e5a4258ce00a314&oe=589AAD2F

но для этого URL string url = Request.Query["url"].Value.ToString(); неполна и отсутствует последняя часть (& oe = 589AAD2F), поэтому ответы сервера с Запрещенным.

enter image description here

Вот простое изменение, чтобы продемонстрировать эту проблему:

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", 
     "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 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 перед его отправкой, а Нэнси будет автоматически декодировать URL для нас, следовательно, не нужно ничего менять на стороне сервера.

Вот пример ссылки, генерируемого с использованием HttpUtility.UrlEncode наносится на

https://scontent.xx.fbcdn.net/v/t1.0-1/c15.0.50.50/p50x50/10354686_10150004552801856_220367501106153455_n.jpg?oh=6c801f82cd5a32fd6e5a4258ce00a314&oe=589AAD2F

Результат:

HTTPS% 3a% 2f% 2fscontent.xx.fbcdn.net% 2fv% 2ft1.0- 1% 2fc15.0.50.50% 2fp50x50% 2f10354686_10150004552801856_220367501106153455_n.JPG% 3foh% 3d6c801f82cd5a32fd6e5a4258ce00a314% 26oe% 3d589AAD2F

и фактический запрос данной ссылке будет:

http://localhost:9876/?url=https%3a%2f%2fscontent.xx.fbcdn.net%2fv%2ft1.0-1%2fc15.0.50.50%2fp50x50%2f10354686_10150004552801856_220367501106153455_n.jpg%3foh%3d6c801f82cd5a32fd6e5a4258ce00a314%26oe%3d589AAD2F

Альтернативное решение

Я лично предпочитаю POST через GET в этом ситуация, поэтому вот оно:

public class ReverseProxyController : NancyModule 
{ 
    class ProxyRequest 
    { 
     public string Url { get; set; } 
    } 

    public ReverseProxyController() 
    { 
     Post["/", true] = async (parameters, ct) => 
     { 
      var result = await GetResult(parameters, ct); 
      return result; 
     }; 
    } 

    private async Task<Response> GetResult(dynamic parameters, 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", "*"); 
     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 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); 
     } 
    } 
} 
+0

Это проблема. Я только что проверил, прежде чем увидел этот ответ, и ему не хватает последнего «& oe = 589AAD2F». – richard

+0

Почему nancy усекает этот последний параметр запроса? – richard

+0

Nevermind ... Нэнси усекает его из-за того, как Нэнси символизирует URL-адрес ... это дает мне то, что, по его мнению, является параметром, который я хочу. Есть ли способ правильно отформатировать маршрут, чтобы получить то, что я хочу? – richard

1

как консольное приложение, код которого отлично работает

static void Main(string[] args) 
    { 
     GetStuff(); 
     Console.ReadLine(); 
    } 

    private static async void GetStuff() 
    { 
     CancellationToken ct = new CancellationToken(); 
     var client = new HttpClient(); 
     //this is only a Simple Change to demonstrate the problem, and should not be considered as a proper solution 

     string url = "https://scontent.xx.fbcdn.net/v/t1.0-1/c15.0.50.50/p50x50/10354686_10150004552801856_220367501106153455_n.jpg?oh=6c801f82cd5a32fd6e5a4258ce00a314&oe=589AAD2F"; 
     if (url == null) return; 

     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 System.Net.HttpStatusCode.OK: 
       var stream = await response.Content.ReadAsStreamAsync(); 


       break; 
      default: 
       break; 
     } 
    } 

Я получаю сообщение возврата OK 200. Используются ли другие изображения, которые могут вам понадобиться для регистрации?

Смежные вопросы