0

I have a HUGE request whose contents are in a file. I am getting an error, and I do not know why; I have this code:

$creds = "UN" + ":" + "PW"
$strCusips = $cusips -join ","
$req1 =  -join("GET,(", $strCusips, "),(stuff),,, ,Titles=SHORT,DATEFORM=YMD")
$request = "Request=" + [System.Net.WebUtility]::UrlEncode($req1)
$request > "temp.txt"
$response = curl.exe POST --silent --user $creds --data '@temp.txt' http://url/cgi/stuff

But this produces the following:

Post Method invoked, but no request found!

To be clear - the file contains something like this... (But is actually much bigger)

Request=GET%2C(0003128%2C0005588%2C0016308%2C0021216%2C0028262%2C0045614%2C0047245%2C0053673%2C0056650%2C0059585)%2C(stuff)%2C%2C%2C+%2CTitles%3DSHORT%2CDATEFORM%3DYMD

What gives? Is this an encoding issue? Is it not supposed to be URL encoded? Or is it?

EDIT:

To be a little more clear, this works perfectly:

$creds = "UN" + ":" + "PW"
$strCusips = $cusips -join ","
$req1 =  -join("GET,(", $strCusips, "),(stuff),,, ,Titles=SHORT,DATEFORM=YMD")
$request = "Request=" + [System.Net.WebUtility]::UrlEncode($req1)

$response = curl.exe POST --silent --user $creds --data $request http://url/cgi/stuff

(Please note all I did was pass the string to the curl request, as opposed to saving it to a file and then passing the file.)

ALSO, this works, so I know I can read the file, and its contents exist and are correct:

Get-Content temp.txt

EDIT2:

I have tried every --data-* flag that curl has, and they all produce the same result.

EDIT3:

This is what I run, with results:

$strCusips1 = $cusips[0..9] -join ","
$req1 =  -join("GET,(", $strCusips1, "),(CNTYRISKtxt),,,,Titles=SHORT,")
$request1 = "Request=" + [System.Net.WebUtility]::UrlEncode($req1)
$request1 > temp.txt
Get-Content temp.txt
curl.exe -v --user $creds --data-raw '@temp.txt' http://url/cgi/stuff


Request=GET%2C(0003128%2C0005588%2C0016308%2C0021216%2C0028262%2C0045614%2C0047245%2C0053673%2C0056650%2C0059585)%2C(CNTYRISKtxt)%2C%2C%2C%2
CTitles%3DSHORT%2C
curl.exe :   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
At line:26 char:1
+ curl.exe -v --user $creds --data-raw '@temp.txt' http:// ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (  % Total    % ...  Time  Current:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
*   Trying x.x.x.x...
* TCP_NODELAY set
* Connected to url (x.x.x.x) port 80 (#0)
* Server auth using Basic with user 'user'
> POST /cgi/stuff HTTP/1.1
> Host: http://url/cgi/stuff
> Authorization: Basic xxxxxxxxxxxxx
> User-Agent: curl/7.52.1
> Accept: */*
> Content-Length: 9
> Content-Type: application/x-www-form-urlencoded
> 
} [9 bytes data]
* upload completely sent off: 9 out of 9 bytes
* HTTP 1.0, assume close after body
< HTTP/1.0 200 Script results follow
< Content-type: text/plain
< 
{ [43 bytes data]
* Curl_http_done: called premature == 0
100    52    0    43  100     9    551    115 --:--:-- --:--:-- --:--:--   551
Post Method invoked, but no request found!
* Closing connection 0

PS C:\Users\lhawk> 
lukehawk
  • 1,423
  • 3
  • 22
  • 48
  • Is this a new job, a manual job being converted to a script, or an existing job being converted to a new language? It is not clear if you are starting from scratch or trying to mimic some existing process. –  Aug 10 '17 at 14:47
  • This is new. I need to query an API for data, and for reasons unimportant, I have to use powershell to do it. – lukehawk Aug 10 '17 at 15:40
  • Why can't you use --data $request? –  Aug 10 '17 at 16:50
  • This produces a string too long to pass to curl. The request can be huge. – lukehawk Aug 10 '17 at 17:07
  • For whatever it is worth - it seems like 32,635 characters is the most I can pass. Passing a string of 32,636 causes an error - `Program 'curl.exe' failed to run: The filename or extension is too long.` – lukehawk Aug 10 '17 at 17:51
  • 1
    That `POST` string you have in the command line should be removed. – Daniel Stenberg Aug 10 '17 at 18:12
  • Thanks @Daniel. I removed it but it seems to have no effect. Still says no request is found (I cannot remember why, but I remember thinking I needed it when I originally wrote this....) – lukehawk Aug 10 '17 at 18:59
  • Is there any specific reason for using Curl instead of Invoke-WebRequest or a .net webclient (or any other "built in" features)? Also keep in mind that Get-Content is kinda tricky. You can try the -Raw switch, just using get-content without the raw switch puts the result in a string array. – bluuf Aug 11 '17 at 16:34
  • Invoke-WebRequest, from what I have been able to tell, cannot handle HTTP1.0 in the response. Also, I had a hell of a time getting the credentials to work (though I eventually did). I like using cURL because it is easy and always works. (Until now...) Finally, I only used `Get-Content` to display the content in the file to demonstrate it does contain what I want it to. It is meaningless in the code. – lukehawk Aug 11 '17 at 16:59
  • What other 'builtin' features are there I could use? Other than Invoke-WebRequest? – lukehawk Aug 11 '17 at 16:59

1 Answers1

0

In your last example,

curl.exe -v --user $creds --data-raw '@temp.txt' http://url/cgi/stuff

produces

> Content-Length: 9

 @temp.txt
01234567890123456789
         ^ nine bytes            

So switch the command back to -d to grab the file contents.

curl.exe -v -u $creds -d '@temp.txt' http://url/cgi/stuff
                      ^^                                 

That should be fine since you are encoding the response.

$request = "Request=" + [System.Net.WebUtility]::UrlEncode($req1)

curl -v further shows that Post Method invoked, but no request found! is coming from the server.

< HTTP/1.0 200 Script results follow
< Content-type: text/plain
< 
{ [43 bytes data]
* Curl_http_done: called premature == 0
100    52    0    43  100     9    551    115 --:--:-- --:--:-- --:--:--   551
Post Method invoked, but no request found!
* Closing connection 0

That will be true regardless of the different syntax errors.

Twice you mentioned that strings are working.

EDIT:

To be a little more clear, this works perfectly:

$creds = "UN" + ":" + "PW"
$strCusips = $cusips -join ","
$req1 =  -join("GET,(", $strCusips, "),(stuff),,, ,Titles=SHORT,DATEFORM=YMD")
$request = "Request=" + [System.Net.WebUtility]::UrlEncode($req1)

$response = curl.exe POST --silent --user $creds --data $request http://url/cgi/stuff

(Please note all I did was pass the string to the curl request, as opposed to saving it to a file and then passing the file.)

and

The request is good, since I can pass it as a string just fine, and get the desired results.

So, I think the problem is the encoding done by >.

"a happy string" > temp.txt

produced a text file encoded in UCS-2 LE BOM. And the file ends in a newline.

Though, the newline does not matter.

-d, --data <data>

...

If you start the data with the letter @, the rest should be a file name to read the data from, or - if you want curl to read the data from stdin. Multiple files can also be specified. Posting data from a file named 'foobar' would thus be done with -d, --data @foobar. When --data is told to read from a file like that, carriage returns and newlines will be stripped out. If you don't want the @ character to have a special interpretation use --data-raw instead.

Previously, I wrote a function to work around PowerShell's default encoding. So, let's use the function to see if the file's encoding is the issue.

function giveBinaryEqualFile ([string] $myInput, [string] $fileName)
{
    $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
    [System.IO.File]::WriteAllText($fileName, $myInput, $Utf8NoBomEncoding)
}

# $request > "temp.txt" becomes 
$myFile = "C:\full\path\temp.txt" 
giveBinaryEqualFile $request $myFile

# $response = curl.exe -v --user $creds --data-raw '@temp.txt' http://url/cgi/stuff becomes 
$response = curl.exe -v --user $creds --data '@temp.txt' http://url/cgi/stuff
# since you are referencing a file. 
# --data-raw
# https://curl.haxx.se/docs/manpage.html

If this starts working then switch -v to --silent.

  • Thanks! Your first solution provided the same result as mine, but I am trying to use the 'Invoke-WebRequest'. However, I am pretty sure I have tried to use it several times in the past and always seem to run into problems. How do I pass credentials in those lines you wrote? – lukehawk Aug 10 '17 at 17:55
  • Thanks!! But I remember now why I couldn't get Invoke-WebRequest to work. I THINK the response is coming back in HTTP1.0, which violates the HTTP1.1 restrictions. I tried getting into changing some .ini files somehere, but this all seems way too much of a pain to go through, which is why I was trying to use curl. Make sense? Is there a flag or simple way to force Invoke-WebRequest to accept HTTP1.0? – lukehawk Aug 10 '17 at 18:49
  • ok, I'll put HTTP 1.0 on my to do list. For the time being, I'm interested in the cURL path. If you put a breakpoint on your `$response = curl.exe` line and then execute `curl --silent --user user:password --data '@temp.txt' http://url/cgi/stuff` in the shell then does that work? Maybe we're not giving cURL the right path. –  Aug 10 '17 at 19:18
  • I apologize, but I am not following what you mean. If I just run the line in the shell, and have it output to the console, I get the same result. Is that what you mean? – lukehawk Aug 10 '17 at 19:46
  • When I make syntax errors while using cURL, the response gets prefaced with `Warning:` It is clear that cURL is talking. Where is `Post Method invoked, but no request found!` coming from? What does this `curl -v --user user:password --data '@temp.txt' http://url/cgi/stuff` say? –  Aug 10 '17 at 20:55
  • Thanks for your help so far, see Edits. – lukehawk Aug 11 '17 at 14:39
  • cURL is working `< HTTP/1.0 200 Script results follow`. But the request is not `Post Method invoked, but no request found!`. That's the server talking. I don't think the issue is with `$response = curl.exe POST --silent --user $creds --data '@temp.txt' http://url/cgi/stuff`. I think there is a problem with the formatting of the request. Or, the specific requests you submitted were invalid. [Tools That Help You use curl](https://curl.haxx.se/docs/relatedtools.html) might help. –  Aug 15 '17 at 15:56
  • I agree that is not cURL talking, but it is cURL that is not passing the request from the file to the server. The request is good, since I can pass it as a string just fine, and get the desired results. cURL is not taking the contents of the file and sending them to the server, or it is formatting them in some way the server does not recognize. – lukehawk Aug 15 '17 at 16:20
  • Perhaps the file encoding is a problem. Please try the new answer. –  Aug 15 '17 at 17:57