JoeDog / siege

Siege is an http load tester and benchmarking utility
GNU General Public License v3.0
5.97k stars 385 forks source link

Feature added to __parse_post_data function to parse -T argument #239

Closed Gbell26 closed 4 months ago

Gbell26 commented 4 months ago

Siege can only assign content type from the command line or if POST data is saved to a file limiting the ability to hit many endpoints that require different content types in a single siege session.

Feature added to __parse_post_data() to parse -T argument allowing siege to dynamically assign content type per URL in URL file.

Lines in the URL file can be constructed as follows to pass varying content types when passing data:

http://url POST -T application/json; {data}
JoeDog commented 4 months ago

I like it but how are you getting away with this without it being quoted? I would think you'd need this:

http://url POST -T "application/json; {data}"

Gbell26 commented 4 months ago

My understanding is because I am not defining any new string after -T I am just manipulating the existing string that the function is handling. I am treating it very similarly to how the function already acts. I am checking for -T in the string similar to how the __url_parse() function checks for "POST" "PUT" "DELETE" etc. here:

  if (! post) {
   post = strstr(this->url, " PUT");
 }

 if (! post) {
   post = strstr(this->url, " PATCH");
 }

 if (! post) {
   post = strstr(this->url, " OPTIONS");
 }

 if (! post) {
   post = strstr(this->url, " DELETE");
}

and if it exists then changing the ';' delimeter to a null terminator splitting the string into two strings. Then using xstrdup() to copy the first string to this->contenttype the same way it is copying datap to this->postdata. And moving the pointer past the argument similarly to this section that moves past the whitespace:

for (; isspace((unsigned int)*datap); datap++) {
/* Advance past white space */

}

So its mostly working the same way it already was just copying the section between -T and ; first. Does that make sense?

Gbell26 commented 4 months ago

This:

POST -T application/json; {data}

is all already in memory, the __url_parse() function pulls POST|PUT|DELETE etc out and then passes the rest to __parse_post_data(). Before it was just moving past the white space and copying {data} to this->postdata (or loading in the data from file). So now instead of just moving past the white space we check for the -T argument, copy that to this->contenttype then continue on the same way

JoeDog commented 4 months ago

If I do this, it blows up:

$ ./siege -c1 -r1 POST -T application/json; haha=papa https://www.joedog.org/
SIEGE 4.1.7-b6 Preparing 1 concurrent users for battle. The server is now under siege... [error] Address resolution failed at sock.c:158 with the following error:: Resource temporarily unavailable [error] Temporary failure in name resolution: POST: Resource temporarily unavailable

But if I quote it, then it works: $ ./siege -c1 -r1 POST -T "application/json; haha=papa" https://www.joedog.org/siege/echo.php SIEGE 4.1.7-b6 Preparing 1 concurrent users for battle. The server is now under siege... HTTP/1.1 200 0.52 secs: 467 bytes ==> GET /siege/echo.php

But I don't understand why you can't just do this:

$ ./siege -c1 -r1 -T "application/json" "https://www.joedog.org/siege/echo.php POST haha=papa" SIEGE 4.1.7-b6 Preparing 1 concurrent users for battle. The server is now under siege... HTTP/1.1 200 0.60 secs: 488 bytes ==> POST https://www.joedog.org/siege/echo.php

Gbell26 commented 4 months ago

Yes, this is specifically when using the URL file to hit multiple different endpoints. It should have no effect on the way the command line parsing is working.

So the call would be

./siege -c1 -r1 -f url_file.txt

Where url_file.txt looks something like this:

http://url POST -T application/json; {data}
http://url POST -T text/plain; data
etc. 

Previously you would have to pass the content type at the command line which would then apply to all urls in that file.

Or your data would have to be saved to many different files and siege would infer content type based on file extension so it would have to be like this

http://url POST > data.json
http://url POST > data.txt

So this offers a solution allowing you to use the url file and write the data directly to the URL file and while using multiple content-types

Also it is written to only overwrite the contenttype for each line so for example if you had 10 endpoints that want application/json data and only 1 that wants text/plain you should be able to write the url file like this:

http://url POST {data}
http://url POST -T text/plain; data
etc. 

and call siege with:

  ./siege -c1 -r1 -T "application/json" -f url_file.txt

and it will treat application/json as the default and set those endpoints that dont pass -T on the line with that content-type.

JoeDog commented 4 months ago

Previously you would have to pass the content type at the command line which would then apply to all urls in that file.

Okay. I see now. Thanks.

On Fri, Jul 19, 2024 at 11:34 AM Gbell26 @.***> wrote:

Yes, this is specifically when using the URL file to hit multiple different endpoints. It should have no effect on the way the command line parsing is working.

So the call would be

./siege -c1 -r1 -f url_file.txt

Where url_file.txt looks something like this:

http://url POST -T application/json; {data}http://url POST -T text/plain; data etc.

Previously you would have to pass the content type at the command line which would then apply to all urls in that file.

Or your data would have to be saved to many different files and siege would infer content type based on file extension so it would have to be like this

http://url POST > data.jsonhttp://url POST > data.txt

So this offers a solution allowing you to use the url file and write the data directly to the URL file and while using multiple content-types

Also it is written to only overwrite the contenttype for each line so for example if you had 10 endpoints that want application/json data and only 1 that wants text/plain you should be able to write the url file like this:

http://url POST {data}http://url POST -T text/plain; data etc.

and call siege with:

./siege -c1 -r1 -T "application/json" -f url_file.txt

and it will treat application/json as the default and set those endpoints that dont pass -T on the line with that content-type.

— Reply to this email directly, view it on GitHub https://github.com/JoeDog/siege/pull/239#issuecomment-2239472639, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABJRHZWDSYMF2QHHT42N5F3ZNEWZVAVCNFSM6AAAAABLBGKUCGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMZZGQ3TENRTHE . You are receiving this because you commented.Message ID: @.***>

-- Jeff Fulmer 1-717-799-8226 https://www.joedog.org/ He codes