0

We are using external rest API (Vimeo) to upload video from phone to server. One of the steps in performing this operation is to check how many bytes have been uploaded. To do this, PUT request should be performed on specific URL with headers:
- Authorization bearer d4559ba...
- Content-Range bytes */*

Response from the API is either:
- 200 Ok - if upload is completed
- 308 Resume Incomplete - with Range header (e.g. Range bytes=0-1000) giving information how many bytes have been uploaded

Problem is that enum HttpStatusCode (https://developer.xamarin.com/api/type/System.Net.HttpStatusCode/) in Xamarin doesn't contain value 308 and as a result Exception is thrown during call to client.PutAsync: {System.Net.WebException: Invalid status code: 308 ---> System.Net.ProtocolViolationException: Invalid status code: 308 at System.Net.HttpWebRequest.Redirect ... }

Any idea how to work around this error? Here is a C# code that we are using:

        var client = new HttpClient(new NativeMessageHandler() { AutomaticDecompression = DecompressionMethods.Deflate });
        var uri = new Uri(url);

        client.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", Constants.VimeoToken));

        var stringContent = new StringContent("");
        stringContent.Headers.Add("Content-Range", "bytes */*");

        var httpResponse = await client.PutAsync(uri, stringContent);
        return httpResponse;

Edit: I tried using DelegatingHandler with this code:

    public class MyDelegatingHandler : DelegatingHandler
    {
        public MyDelegatingHandler(HttpMessageHandler innerHandler) : base(innerHandler) { }
        protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var response = await base.SendAsync(request, cancellationToken);
            if (!response.IsSuccessStatusCode && response.StatusCode == (HttpStatusCode)308) //This line of code is never reached
            {
            }
            return response;
        }
    }
    var client = new HttpClient(new MyDelegatingHandler(new NativeMessageHandler() { AutomaticDecompression = DecompressionMethods.Deflate }));
    HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Put, url);
    var stringContent = new StringContent("");
    stringContent.Headers.Add("Content-Range", "bytes */*");
    message.Content = stringContent;
    CancellationToken cancellationToken = new CancellationToken();
    var response = await client.SendAsync(message, cancellationToken);

Problem is base.SendAsync throws exception and next line of code (if statement) is not reached. Should I use Delegating handler in another way?

Edit: I tried using RestSharp with this code:

        RestClient client = new RestClient(url);
        var request = new RestRequest("", Method.PUT);
        request.AddHeader("Authorization", string.Format("Bearer {0}", Constants.VimeoToken));
        request.AddHeader("Content-Range", "bytes */*");
        var response = await client.Execute(request);

With this request I receive wrong status code which means request is not properly created. Maybe Content-Range header is not added correctly and Vimeo server is not able to read it. Is there another way to add this header?

Uros
  • 2,099
  • 7
  • 23
  • 50
  • Create a `DelegatingHandler` and use that with the client in order to handle the 308 status code without blowing up.. – Nkosi Jan 24 '17 at 16:31
  • What native `NativeMessageHandler` are you using? I have no problems with 308s using `HttpClient` and the native `NSUrlSession` or `AndroidClientHandler` set as the HttpClient implementation... – SushiHangover Jan 24 '17 at 18:22
  • NativeMessageHandler is part of ModernHttpClient which is using OkHttp on Android and NSURLSession or AFNetworking on iOS. If I change message handler it will still use HttpStatusCode which doesn't contain 308. – Uros Jan 25 '17 at 09:43
  • @Nkosi: I tried using DelegatingHandler but I don't know how to properly handle 308 status code without blowing up. Can you share some code? – Uros Jan 27 '17 at 09:20

2 Answers2

0

You can put try - catch' around PutAsync it and inspect the status code. If it is 308 handle that case.

Moutabreath
  • 184
  • 1
  • 6
  • 19
0

If you use HttpWebRequest you can set HttpWebRequest.AllowAutoRedirect to false to avoid this exception. I haven't tried HttpClient.AllowAutoRedirect but it may work.

If you are using a PCL library you need to either use reflection or Dependency injection to get access to the property.

Paul Kiar
  • 236
  • 4
  • 3