Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RestTemplate with InputStreamResource does not work if Content-Length is not set [SPR-12017] #16633

Closed
spring-projects-issues opened this issue Jul 21, 2014 · 3 comments
Assignees
Labels
status: backported An issue that has been backported to maintenance branches type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Jul 21, 2014

John Mark opened SPR-12017 and commented

When using an InputStreamResource to upload a file for example

...
MultiValueMap<String, Object> postData = new LinkedMultiValueMap<>();
postData.add("param", "something");
postData.add("file", new InputStreamResource(in));

restTemplate.postForObject(url, postData, String.class);

This causes a strange exception to be thrown: IllegalStateException: InputStream has already been read....

Looking through the code it appears that what is occurring is when AbstractResource.contentLength() is called, it actually reads the entire InputStream. This makes it impossible to use InputStreamResource without defining the Content-Length header. It would be nice if this were not the case. Or if this is required for some reason, at least it should be documented so other people don't have to waste time debugging like I had to.


Affects: 3.2.10, 4.0.6

Issue Links:

Referenced from: commits e14aad8, 5342d92, f0bcb77

Backported to: 3.2.11

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

The problem here is that with an InputStreamResource, the given InputStream can technically only be read once. It's unfortunate here that AbstractResource's contentLength() implementation performs that one read attempt and therefore renders the InputStreamResource unusable afterwards. I guess we should rather throw an IllegalStateException from an InputStreamResource-specific contentLength() implementation, signalling that the content length cannot be determined without side effects. RestTemplate and other callers can deal with that accordingly then, simply not knowing the content length in advance.

That said, it's definitely recommendable to use one of the more specific Resource implementations if you can, which among other benefits are usually capable of determining the content length without side effects. InputStreamResource should be a last resort only.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Alternatively, we could also let RestTemplate check for an InputStreamResource and simply not call contentLength() on it in that case, since it knows that the InputStreamResource will be used for full content reading afterwards.

For other kinds of callers, just determining the contentLenght() might be alright if they never end up reading the actual content afterwards.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

As of 4.1 RC2, ResourceHttpMessageConverter does not call contentLength() on InputStreamResource anymore. To be backported to 4.0.7 and 3.2.11.

Juergen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: backported An issue that has been backported to maintenance branches type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants