-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Allow a blank/empty ContentType to be passed to Invoke-WebRequest for compatibility with PS6 and earlier #11421
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
Allow a blank/empty ContentType to be passed to Invoke-WebRequest for compatibility with PS6 and earlier #11421
Conversation
…no body. Regarding `Invoke-WebRequest`: A change was made to PowerShell Core with commit `2285ece613` that changes the way web request headers are handled when the web request has no body. Previously, they would be ignored. Now, they are processed anyway, including the `ContentType` header, which makes no sense when there's no body. Now, the headers are processed anyway, and if there's a `ContentType` header with an empty string value, it will fail. When a customer tries to pass in a blank (i.e., `$null`) `ContentType` to a function that takes a `string` because they have no body, it gets treated as an empty string, not `$null`. This works fin in Windows PowerShell (PS5 and earlier) and PowerShell Core 6, because their code bases don't have commit `2285ece613`. When it fails, they get a message saying that they can avoid this by passing `-SkipHeaderValidation`, but this flag isn't available in Windows PowerShell, and using it would require a crude hard-coded version check to see if you're on Windows PowerShell or PowerShell Core. This change merely skips adding headers to the request if the header value is nothing (null or whitespace). **Question**: Should we only do this *skip* for the `ContentType` header? PowerShell#11396
Fix for issue 11396 regarding blank ContentType for web request with no body
jazzdelightsme
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Collecting some discussions about empty HTTP headers from elsewhere:
From the Fetch issue referenced by Steve:
I'm sorry but can someone just say Yes or No whether empty header values are legal HTTP?
Are they allowed by HTTP? Yes. Are they allowed / defined to have meaning for an individual header field? It depends on the field's definition. That said, it's not good practice to do it.
And dotnet seems to currently enforce the "it's not a good idea to do it" opinion (it rejects empty headers).
Suppose at some point, the dotnet Issue was addressed, and they decided to allow empty headers. Would we (PowerShell) then want to expose that ability in PS (to have an empty header value)? We could remove this null/empty check, and then the dotnet API would allow it… and it would be sent to the server. Would the HTTP server allow it? Dunno. So that could be a breaking change, too.
Or we could just say "no, you just can't send empty headers with PS". Given that that is already the case (you can't send an empty HTTP header, else dotnet throws (although I don't know if that behavior has always been that way with dotnet)), and nobody has complained (actually I have no idea if anyone has complained, but it hasn't become a blocking issue that has been addressed--I'm relying on actual PS people to validate what I'm saying here), it seems like a reasonable position to stick to.
Given all that, I think this change looks good.
|
One option to make it even more future-proof would be to add another condition to this check, and only ignore blank headers if the body is also empty or non-existent. Then, it will actually behave closer to the PS6 version of the code, which doesn't allow any custom headers if there's no body. |
|
@spongemike2 I may lack some context or experience in this area, but from memory there are some perfectly valid requests that can be made with headers and no body, aren't there? |
|
@vexx32, I am not an expert in this area, but if I had to guess, I would say yes, which is presumably why the change was made that broke this. However, headers that have no value? I think that's unlikely to be useful. Rather than specifying a header with a blank value, which dotnetcore doesn't allow, one could get effectively the same information conveyed by omitting the header altogether. Which is why I think (even though I'm not 100% sure) that my change should be safe. |
| if (!string.IsNullOrWhiteSpace(entry.Value)) | ||
| { | ||
| try | ||
| if (SkipHeaderValidation) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If our intention is to follow Core (that is to send headers with empty value) the check should be here: Update.
Also please add a test.
SteveL-MSFT
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a test? I believe there is an existing test case to validate headers are passed, so just augment it with an empty header.
|
Test added. Verified that the new test fails prior to this change, and succeeds with it. |
|
@spongemike2 could you edit the PR title summary to something a bit more descriptive? Thanks! 😊 |
Done. |
test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1
Outdated
Show resolved
Hide resolved
|
Anything else needed? |
|
I think It is a breaking change and we should add CL-BreakingChange |
|
It looks to me a regression we made in 7.0 time frame and we are fixing it before 7.0 GA. It's a behavior changes only comparing with 7.0 previews, so I think it's not a breaking change. But do let me know if I'm missing something. |
I agree. It would have been an unknown breaking change if it wasn't fixed before GA, but we caught it and fixed it. |
|
I agree if this will be in GA. |
…mpty value for backward compatibility (#11421)
|
🎉 Handy links: |
PR Summary
Regarding
Invoke-WebRequest:A change was made to PowerShell Core with commit
2285ece613that changes the way web request headers are handled when the web request has no body. Previously, they would be ignored. Now, they are processed anyway, including theContentTypeheader, which makes no sense when there's no body. Now, the headers are processed anyway, and if there's aContentTypeheader with an empty string value, it will fail.When a customer tries to pass in a blank (i.e.,
$null)ContentTypeto a function that takes astringbecause they have no body, it gets treated as an empty string, not$null.This works fin in Windows PowerShell (PS5 and earlier) and PowerShell Core 6, because their code bases don't have commit
2285ece613.When it fails, they get a message saying that they can avoid this by passing
-SkipHeaderValidation, but this flag isn't available in Windows PowerShell, and using it would require a crude hard-coded version check to see if you're on Windows PowerShell or PowerShell Core.This change merely skips adding headers to the request if the header value is nothing (null or whitespace).
Question: Should we only do this skip for the
ContentTypeheader?Fix #11396
PR Context
Without this, PS scripts that run fine in Windows PowerShell and PowerShell Core 6 break.
PR Checklist
.h,.cpp,.cs,.ps1and.psm1files have the correct copyright headerWIP:or[ WIP ]to the beginning of the title (theWIPbot will keep its status check atPendingwhile the prefix is present) and remove the prefix when the PR is ready.