Byron/google-apis-rs

`Content-Length` header missing when no body was provided in post request, causing request failure

Dreaming-Codes opened this issue · 19 comments

Hi, the latest schema update introduced a new method google_play_console_hub..purchases().products_consume which is a fundamental method to consume a bought product to allow the user to buy it again but that method always gives me the following error:

Http status indicates failure: Response { status: 411, version: HTTP/1.0, headers: {"content-type": "text/html; charset=UTF-8", "referrer-policy": "no-referrer", "content-length": "1564", "date": "Sat, 09 Mar 2024 11:16:57 GMT"}, body: Body(Full(b"\n\n \n <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">\n <title>Error 411 (Length Required)!!1</title>\n <style>\n {margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px} > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}\n </style>\n \n

411. That\xe2\x80\x99s an error.\n

POST requests require a Content-length header. That\xe2\x80\x99s all we know.\n")) }

There cannot be support for any of the generated APIs, they are provided by Google. This repository is about the generator itself, and no other support can be provided here.
Thanks for your understanding.

@Byron Please read what I added above as a comment

Comparing it with another post request in the generated code it seams like this part is missing products_acknowledge: https://github.com/Byron/google-apis-rs/blob/ef8dc60e716dba545453f70caca23ac97427fe6c/gen/androidpublisher3/src/api.rs#L36398-L36408

https://github.com/Byron/google-apis-rs/blob/ef8dc60e716dba545453f70caca23ac97427fe6c/gen/androidpublisher3/src/api.rs#L36696

You can try different versions of the generated code, there is 5.0.3 and 5.0.4, which uses different versions of the API.

@Byron nope products_consume is a new method

@Byron I think that this is a bug in the generator since it's skipping a required post header

Please feel free to submit a PR with a fix. If that allegedly missing header can't be inferred from the API description, maybe the API can be changed to allow the user to inject their own headers.

Please feel free to submit a PR with a fix. If that allegedly missing header can't be inferred from the API description, maybe the API can be changed to allow the user to inject their own headers.

@Byron The header missing is a required http header not a custom one, it's Content-length
I mean a post request should always have that even if not specified in the API description

I would fix that, but I really don't know how Mako works.

You can probably look at the generated code to see under which circumstances it does or doesn't add that header.

@Byron the only difference that I notice from other post requests is the missing request key
acknowledge:

"request": {
"$ref": "ProductPurchasesAcknowledgeRequest"
},

consume:

"consume": {
"description": "Consumes a purchase for an inapp item.",
"flatPath": "androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}:consume",
"httpMethod": "POST",
"id": "androidpublisher.purchases.products.consume",
"parameterOrder": [
"packageName",
"productId",
"token"
],
"parameters": {
"packageName": {
"description": "The package name of the application the inapp product was sold in (for example, 'com.some.thing').",
"location": "path",
"required": true,
"type": "string"
},
"productId": {
"description": "The inapp product SKU (for example, 'com.some.thing.inapp1').",
"location": "path",
"required": true,
"type": "string"
},
"token": {
"description": "The token provided to the user's device when the inapp product was purchased.",
"location": "path",
"required": true,
"type": "string"
}
},
"path": "androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}:consume",
"scopes": [
"https://www.googleapis.com/auth/androidpublisher"
]
},

I think that I found the problem. basically when there's no body the generator does not add the Content-length header

https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.products/consume#request-body

Thanks for the research.
That sounds like something fixable, even though a fix will have to be contributed.

I think that the error in the generation happens here

% if not simple_media_param:
let request = req_builder
.header(CONTENT_TYPE, json_mime_type.to_string())
.header(CONTENT_LENGTH, request_size as u64)
.body(hyper::body::Body::from(request_value_reader.get_ref().clone()))\
% else:
let mut body_reader_bytes = vec![];
body_reader.read_to_end(&mut body_reader_bytes).unwrap();
let request = req_builder
.header(CONTENT_TYPE, content_type.to_string())
.body(hyper::body::Body::from(body_reader_bytes))\
% endif ## not simple_media_param

It may be enough to add .header(CONTENT_LENGTH, 0_u64) between lines 761 and 762.

It appears like it, and is a strange omission as well. You can probably try it locally, and even if not, CI will be able to validate the generated code is still correct.

@Byron I'm trying to get nix on my system to work so I can get python 3.8

Getting a local dev setup is harder than it should be due to needing python, thus I recommend creating a PR with this seemingly trivial change (blindly, if you will), and see if that works.

For local testing, the change can be added by hand in the generated code, and used with your application via [patch."crates-io"] section in the Cargo manifest.

Getting a local dev setup is harder than it should be due to needing python, thus I recommend creating a PR with this seemingly trivial change (blindly, if you will), and see if that works.

@Byron I've create a pull request with a .devcontainer for easier development

#477