philipp.hofmann 4 Posted October 10, 2023 The following curl-test works fine on my machine: curl -X POST https://pushinglimits.club/api/oauth/upload_single_fit_file -H 'Content-Type: multipart/form-data' -H 'Authorization: Bearer ...' -F 'file=@Philipp_(SF6KICKR)_20231003_1941_Freies_Training_Training.fit' But the corresponding Delphi-Code will return 10:29:08.213 16488-Info Response: 404 Not Found: <!DOCTYPE html> <html lang="en"><head><meta charset="utf-8"><title>Error</title></head><body><pre>Cannot POST /oauth/upload_single_fit_file</pre></body></html> What could be a difference between both calls? I try to join the GenerateBoundary in System.Net.Mime but it's still not working. Http: TNetHTTPClient; formData: TMultipartFormData; headers: TNetHeaders; Http:=TNetHTTPClient.create(nil); Http.SecureProtocols := [THTTPSecureProtocol.TLS12]; formData:=TMultipartFormData.create(); headers:=TNetHeaders.create(); setLength(headers, 2); headers[0]:=TNameValuePair.create('Content-Type', 'multipart/form-data'); headers[1]:=TNameValuePair.create('Authorization', 'Bearer ' + bearer); formData.AddFile('file', filename); Http.Post('https://pushinglimits.club/api/oauth/upload_single_fit_file',formData,nil,headers); Share this post Link to post
philipp.hofmann 4 Posted October 10, 2023 Info: I was successful with the following code (using Indy now): with TIdHTTP.Create(nil) do try var FIdSSLIOHandlerSocketOpenSSL:TIdSSLIOHandlerSocketOpenSSL:=TIdSSLIOHandlerSocketOpenSSL.Create(nil); var Params: TIdMultiPartFormDataStream; filename:=StringReplace(Training.filename, '.ictt', '.fit', [rfIgnoreCase]); FIdSSLIOHandlerSocketOpenSSL.SSLOptions.Method := sslvTLSv1_2; FIdSSLIOHandlerSocketOpenSSL.SSLOptions.SSLVersions := [sslvTLSv1_2]; IOHandler := FIdSSLIOHandlerSocketOpenSSL; Request.ContentType := 'multipart/form-data'; Request.CustomHeaders.add('Authorization: Bearer ' + bearer); Params := TIdMultiPartFormDataStream.Create; try params.AddFile('file', filename, GetMIMETypeFromFile(filename)); ResponseStr := Post('https://pushinglimits.club/api/oauth/upload_single_fit_file', Params); finally Params.Free; end; finally Free; end; 1 Share this post Link to post
Die Holländer 45 Posted October 10, 2023 Is it only me wondering why people are using more and more inline variable declarations in Delphi code? with TIdHTTP.Create(nil) do try var FIdSSLIOHandlerSocketOpenSSL:TIdSSLIOHandlerSocketOpenSSL:=TIdSSLIOHandlerSocketOpenSSL.Create(nil); var Params: TIdMultiPartFormDataStream; Share this post Link to post
philipp.hofmann 4 Posted October 10, 2023 Sorry, this was copy and paste from an example and it's only to demonstrate that there is an alternative approach. I won't use inline variables in my projects normally. Share this post Link to post
Uwe Raabe 2059 Posted October 10, 2023 IMHO using inline variables and with together looks somewhat strange. 2 Share this post Link to post
Remy Lebeau 1403 Posted October 10, 2023 (edited) 11 hours ago, philipp.hofmann said: What could be a difference between both calls? Did you notice the URL is different in the response HTML? The leading /api was removed. That implies to me (without proof to the contrary - does TNetHTTPClient offer any kind of debug output?) that the server probably didn't like something about the initial request and issued an HTTP redirect to a new URL that happens to not exist. Sounds like a problem with the way the server is processing TNetHTTPClient's reequest, considering the same request in TIdHTTP works. Edited October 10, 2023 by Remy Lebeau 2 Share this post Link to post
Remy Lebeau 1403 Posted October 10, 2023 (edited) 11 hours ago, philipp.hofmann said: Info: I was successful with the following code (using Indy now): On a side note, you are leaking the SSLIOHandler object. You are not assigning it an Owner, so you need to Free() it. Otherwise, I suggest assigning the TIdHTTP at its Owner, eg: var HTTP := TIdHTTP.Create(nil); try var SSL := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP); SSL.SSLOptions.SSLVersions := [sslvTLSv1_2]; HTTP.IOHandler := SSL; HTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + bearer; var Params := TIdMultiPartFormDataStream.Create; try filename := StringReplace(Training.filename, '.ictt', '.fit', [rfIgnoreCase]); params.AddFile('file', filename); ResponseStr := HTTP.Post('https://pushinglimits.club/api/oauth/upload_single_fit_file', Params); finally Params.Free; end; finally HTTP.Free; end; Edited October 10, 2023 by Remy Lebeau 1 Share this post Link to post
Robert Gilland 5 Posted November 5 On 10/10/2023 at 6:42 PM, philipp.hofmann said: headers[1]:=TNameValuePair.create('Authorization', 'Bearer ' + bearer); I am trying the same and with TNetHttpClient and getting an error: Error adding header: (87) The parameter is incorrect when I have an authorization header. Share this post Link to post
hsvandrew 23 Posted November 5 (edited) I've used TNetHTTPRequest to setup a request with headers successfully like this: NetHTTPRequest1.CustomHeaders['Content-Type'] = 'text/html'; Typical object setup is like this NetHTTPClient1 := TNetHTTPClient.create(nil); NetHTTPRequest1 := TNetHTTPRequest .create(nil); NetHTTPRequest1.Client := NetHTTPClient1; Usage NetHTTPRequest1.post( url , data , outcome ); Edited November 5 by hsvandrew Share this post Link to post