reactiveui / refit

The automatic type-safe REST library for .NET Core, Xamarin and .NET. Heavily inspired by Square's Retrofit library, Refit turns your REST API into a live interface.
https://reactiveui.github.io/refit/
MIT License
8.59k stars 746 forks source link

[BUG] Error trying to send a simple image with multipart (Xamarin.iOS) #1312

Open jkapsouras opened 2 years ago

jkapsouras commented 2 years ago

Hello!

I am trying to send an image using a multipart api call to my server. The api call is working from postman. The api call has two params {{domain}}/api/user/data-logs?type=WEIGHT&value=99&dateTime=2022-02-02 (value and dateTime) and has form-data in body with key = image and value the image file. So in my project I have these: The api call: [Multipart] [Post("/api/user/data-logs?type=WEIGHT&value={weight}&dateTime={date}")] IObservable<string> AddWeight(string weight, string date, [AliasAs("image")]StreamPart stream, [Header("Authorization")] string token); I get an error from server (403) and I am trying to find out what is different in my call comparing to postman call. The only thing I can see is that in my call there is an extra filename*=utf-8''851DAB63-CE47-4077-A733-E2794D7F0D81.jpeg and I am not sure if this is what causes the problem. I attach the responses from both my app and postman (from proxyman app) in order to help me if you can. I also attach the multipart tab from proxyman. You can see in this tab that in the file exists in the postman request, while the file does not exist in the request made from my app. Any help is appreciated.

Screenshot 2022-02-09 at 4 45 30 PM Screenshot 2022-02-09 at 4 45 41 PM Screenshot 2022-02-09 at 4 50 46 PM Screenshot 2022-02-09 at 4 50 54 PM
jkapsouras commented 1 year ago

I finally figured this out with some help from out backend guy. It seems that nginx server does not like the quotes. This is the error that we tracked in the server:

[client 94.71.137.154] ModSecurity: Access denied with code 403 (phase 2). Match of "eq 0" against
 "MULTIPART_STRICT_ERROR" required.
 [file "/etc/httpd/conf/modsecurity.d/rules/comodo_free/12_HTTP_Protocol.conf"] [line "30"] [id "210240"] 
[rev "4"] [msg "COMODO WAF: Multipart request body failed strict validation:
 PE 1, BQ 1, BW 0, DB 0, DA 0, HF 0, LF 0, SM , IQ 0, IH 0, FLE 0||xxx.xxxx.xxx.xx|F|2"]
 [severity "CRITICAL"] [tag "CWAF"] [tag "Protocol"] [hostname "xxx.xxxx.xxx.xx"] 
[uri "/xx/xxx/x"] [unique_id "xxx"]

So I added some code to the DelegatingHandler I already had for logging. This is what I added before the SendAsync function.

var boundaryParameter =
                req.Content?.Headers?.ContentType?.Parameters?.SingleOrDefault(p => p.Name == "boundary");

            //check if the api call is multipart
            if (boundaryParameter != null)
            {
                //remove quotes form boundary
                boundaryParameter.Value = boundaryParameter.Value.Replace("\"", "");

                var cont = req.Content as MultipartFormDataContent;
                //remove filename* parameter that has single quotes that also causes rejection from server
                var tmp = cont.First(x => x.Headers.ContentDisposition != null).Headers.ContentDisposition.Parameters
                    .FirstOrDefault(p => p.Name == "filename*");
                cont.First(x => x.Headers.ContentDisposition != null).Headers.ContentDisposition.Parameters.Remove(tmp);
            }

I think you can close this issue since I managed to send multipart requests but maybe something like the above should be added to next versions since nginx servers are pretty common.

jkapsouras commented 1 year ago

This solution applies also to https://github.com/reactiveui/refit/issues/408

Cassiopeja commented 1 year ago

@jkapsouras, thank you for your solution! I`ve encountered similar problem with nginx.