Search code examples
powershellvariablesescapingstring-interpolationinvoke-webrequest

POST request variables powershell


I have a powershell post request using Invoke-WebRequest but when I include the ? it thinks its all one variable, any way to escape this, here is my code

Invoke-WebRequest -UseBasicParsing -Method POST https://192.168.240.1:443/recive/$name?result=$sendback

It thinks name and everything after is a variable, I know this as I can see it all highlighted green in winddows terminal


Solution

  • To complement jswanson's effective solution:

    While placing ` (a backtick, PowerShell's escape character) before the first post-variable-name character is situationally an option[1] (in unquoted and double-quoted arguments), there is a direct way to delimit variable names in (implicit) expandable strings: Enclose the name in {...}, e.g. ${name}:

    Write-Output https://192.168.240.1:443/receive/${name}?result=$sendback
    

    While something like ${name}? is more cumbersome to type than $name`?, it has two distinct advantages:

    • It is more readable (visually distinct).
    • It works in all cases, whereas `-escaping the post-name character could accidentally turn that character into an escape sequence; e.g., say variable $foo should be followed by literal bar:
      • Write-Output $foo`bar - Broken, because the `b becomes a backspace character.
      • Write-Output ${foo}bar - OK, thanks to {...} enclosure

    Optional reading: Why does PowerShell allow ? in identifiers (variable names)?

    Most scripting and programming languages do not allow ? to be part of identifiers such as variable names, typically because ? is a metacharacter (a character with special meaning).

    Even though ? in PowerShell has special meaning too, depending on context, ? in identifiers (variable names, function names, alias names, ...) are permitted.

    While it is commendable on the one hand that PowerShell allows identifiers containing unusual characters, it would make sense to require {...} enclosure for such names[2] - as indeed is already required for other unusual characters, notably . and -:

    # With ".", {...} is required.
    PS> ${foo.bar} = 'bar'; ${foo.bar} # Without {...}, .bar would be a *property access*.
    bar
    

    Regrettably, use of ? does not require {...}:

    # !! With "?", {...} is NOT required.
    PS> $foo? = 'bar'; $foo?
    bar
    

    This behavior actively interferes with the PowerShell (Core) v7.1+ null-conditional operators, ?. and ?[].

    For instance, say I want null-conditional access to a property of variable $var:

    # FAILS, because "?" is considered part of the variable name.
    Set-StrictMode -Version 3; $var = Get-Item foo*.txt; $var?.Length
    

    The error message is InvalidOperation: The variable '$var?' cannot be retrieved because it has not been set.; that is, expression $var?.Length was interpreted as wanting to perform regular property access (.) on a variable named $var? - instead of the intended null-conditional access on variable $var.

    {...} is required in this case even though the name $var itself does not contain special characters:

    # OK, due to {...} - but this shouldn't be necessary
    Set-StrictMode -Version 3; $var = Get-Item foo*.txt; ${var}?.Length
    

    Given that this is both counterintuitive and cumbersome, GitHub proposal #11379 asks for this behavior to be changed. Even though it is technically a breaking change, analysis has revealed that real-world use of variable names ending in ? is vanishingly rare and that, conversely, such use was often erroneous, i.e. based on the expectation that a trailing ? is not a part of a variable name.


    [1] It is only an option if the ` in combination with the first post-variable-name character doesn't accidentally result in an escape sequence; as would happen with t, for instance.

    [2] Note that given that only variable names, not also functions, ..., support {...} enclosure, this would limit ?-containing names to variables.