GideonZ / 1541ultimate

Official GIT archive of 1541 ultimate II sources
GNU General Public License v3.0
178 stars 45 forks source link

U64 [1.43] [3.11] Rest command PUT /v1/drives/<drive>:mount Bad Request #396

Open TomCat666 opened 7 months ago

TomCat666 commented 7 months ago

I am updating my tool for Ultimate64 to use as much of REST API as I can. Most of the stuff works, but drive image mounting always produces "Bad Request" error from the u64 side.

POST /v1/drives/8:mount with or without extra mode/type parameters always gives this error. The same with PUT and using existing image on the u64.

Also while on the subject of Image mounting, will it be possible to RUN a d64/d81 image as with the old API SOCKET_CMD_RUN_IMG in a future update?

GideonZ commented 7 months ago

The issue here is the '8'. This is not a valid drive identifier. You have to use 'a' or 'b'.

TomCat666 commented 7 months ago

Ooooh, thank you :) Closing

TomCat666 commented 7 months ago

The same Bad Request even if using POST /v1/drives/a:mount ... It seems type parameter is mandatory even if you send a proper filename with the request in the Content-Deposition FileName header.

ContentDisposition = {attachment; name=fileUpload; filename=Grey_Preview7+4D_LAXITY.d64}

When I do GET /v1/drives I see filename as "image_file": "/Temp/temp0007",

TomCat666 commented 7 months ago

Checked with WireShark and this is what is sent: POST /v1/drives/a:mount?type=d64 HTTP/1.1 Content-Disposition: form-data; name=Grey_Preview7+4D_LAXITY.d64; filename=Grey_Preview7+4D_LAXITY.d64 Host: 192.168.1.64 Content-Length: 174848 Expect: 100-continue Connection: Keep-Alive

[Full request URI: http://192.168.1.64/v1/drives/a:mount?type=d64]
[HTTP request 1/1]
[Response in frame: 5037]
File Data: 174848 bytes
Data (174848 bytes)

And this is what I get back when I check what is in the drives

"a": { "enabled": true, "bus_id": 8, "type": "1541", "rom": "JiffyDOS1541II.bin", "image_file": "/Temp/temp000B", "image_path": "" }

TomCat666 commented 7 months ago

Some more digging with wireshark. I could get filename to be used by U64 using Postman multipart message. This message works fine and I get the BATTY filename properly on U64:

Hypertext Transfer Protocol POST /v1/runners:load_prg HTTP/1.1\r\n User-Agent: PostmanRuntime/7.36.1\r\n Accept: /\r\n Postman-Token: 63175b70-0a81-4941-97a6-1e882347fc86\r\n Host: 192.168.1.64\r\n Accept-Encoding: gzip, deflate, br\r\n Connection: keep-alive\r\n Content-Type: multipart/form-data; boundary=--------------------------673509399630207895553797\r\n Content-Length: 37280\r\n \r\n [Full request URI: http://192.168.1.64/v1/runners:load_prg] [HTTP request 1/1] [Response in frame: 405089] File Data: 37280 bytes MIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: "--------------------------673509399630207895553797" [Type: multipart/form-data] First boundary: ----------------------------673509399630207895553797\r\n Encapsulated multipart part: (application/octet-stream) Content-Disposition: form-data; name=""; filename="Batty.prg"\r\n Content-Type: application/octet-stream\r\n\r\n Data (37063 bytes) Data: 01080c08c9079effac36353600a00078ee30d04e11d0e601b9d096994003c8d0f74c4003… [Length: 37063] Last boundary: \r\n----------------------------673509399630207895553797--\r\n

However if I do it programatically using .net and I constuct virtually the same message I get an error "NOT FOUND" back from U64:

POST /v1/runners:load_prg HTTP/1.1\r\n
Content-Type: multipart/form-data; boundary="adfebb34-4378-46b9-b6a8-fa0371147a5c"\r\n
Host: 192.168.1.64\r\n
Content-Length: 39104\r\n
Expect: 100-continue\r\n
Connection: Keep-Alive\r\n
\r\n
[Full request URI: http://192.168.1.64/v1/runners:load_prg]
[HTTP request 1/1]
[Response in frame: 414765]
File Data: 39104 bytes

MIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: "adfebb34-4378-46b9-b6a8-fa0371147a5c" [Type: multipart/form-data] First boundary: --adfebb34-4378-46b9-b6a8-fa0371147a5c\r\n Encapsulated multipart part: (application/octet-stream) Content-Disposition: form-data; name=file; filename=Arcadia.prg\r\n Content-Type: application/octet-stream\r\n\r\n Data (38913 bytes) Data: 01080d0800009e283233373229000000333220a7209e2832333732290032080a00973533… [Length: 38913] Last boundary: \r\n--adfebb34-4378-46b9-b6a8-fa0371147a5c--\r\n

Is there something missing in the headers somewhere ?

TomCat666 commented 7 months ago

Found what was the problem. U64 mime parsing couldn't parse boundary string when it was encapsulated with paranthesis:

MIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: "adfebb34-4378-46b9-b6a8-fa0371147a5c"

this works:

MIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: adfebb34-4378-46b9-b6a8-fa0371147a5c

Had to do a bit "hacky" implementation in .net and now it works. I get filenames properly on u64.

GideonZ commented 7 months ago

I guess parenthesis are fine, as long as they are ALSO part of the actual boundary. Everything after the = sign is expected to appear in the boundary. Hmm... you found a corner case that probably needs to be addressed properly.

TomCat666 commented 7 months ago

Unfortunately the boundary string (that points to the actual boundary) in the Multipart Mime has paranthesis but the actual part where the boundary is set does not have them. I have checked and all .net versions have the same problem.

markusC64 commented 7 months ago

Okay, for these questions,the RFC tell what to do. In this case RFC 7578 ( https://datatracker.ietf.org/doc/html/rfc7578#page-4 ).

I cite from section 4.1"Boundary" Parameter of multipart/form-data:

"it is often necessary to enclose the "boundary" parameter values in quotes in the Content-Type headerfield".

Thus,

MIME Multipart MediaEncapsulation, Type: multipart/form-data, Boundary:"adfebb34-4378-46b9-b6a8-fa0371147a5c"

is valid. With »adfebb34-4378-46b9-b6a8-fa0371147a5c« as the boundary.

Greetings

Markus