This is a port written in python for a web service simulator that was original written in javascript by Aron Racho. This version is a full rewrite with several extra features:
Supports plain text responses (you can return a web page, or even test invalid JSON objects). The original tool was used to reply json only.
You can specify the return header to simulate parameters and return codes like 200, 401, 403, etc etc .
You can specify dynamic replies based on post parameters, random numbers, UUIDs or counters
You can write your own python code and send it in the registration post to modify the replies dynamically, connect to a database, or whatever you want. There is no limit.
The server is attached. Just run python server.py
It runs on port 2501 (you can easily change this). It logs requests and responses to ./ws_simulator.log
curl -X POST -H'Content-Type: application/json' -d'{
"endpoint": "/timeout",
"method": "get",
"header":"HTTP/1.1 504 Gateway Timeout\nDate: Fri, 20 June 2008 20:40:34 GMT\nServer:SING\nX-Powered-By: emilio\nConnection:close\nContent-Type: text/plain\n"
}' http://localhost:2501/register
Encode the response (not the header, just the body) python server.py "The URL has moved <a href="http://www.example.com\">" the command returns the encoded base64 string: VGhlIFVSTCBoYXMgbW92ZWQgPGEgaHJlZj0iaHR0cDovL3d3dy5leGFtcGxlLmNvbSI+
curl -X POST -H'Content-Type: application/json' -d'{
"endpoint": "/example",
"method": "get",
"header":"HTTP/1.1 302 Found\nDate: Fri, 20 June 2008 20:40:34 GMT\nServer:SING\nX-Powered-By: emilio\nLocation: http://www.example.com\nConnection:close\nContent-Type: text/plain\n",
"response":"VGhlIFVSTCBoYXMgbW92ZWQgPGEgaHJlZj0iaHR0cDovL3d3dy5leGFtcGxlLmNvbSI+"
}' http://localhost:2501/register
- post to register a new web service specifying the new endpoint and response
- use the new endpoint as a real web service
Dynamic replies are supported by specifying replaceKeys. Valid replaceKeys:
replaces the key by the specified post parameter
initializes an internal counter (you can initialize as many as you want), replaces the key by the current value, and increases the internal counter by one
replaces the key by a random integer in the "X-Y" range. ie: "4-25" to return a random integer between 4 and 25
replaces the key by a newly generated UUID
executes the python code sent. You can basically do anything you want here. The code MUST be encoded in base64. You can store global variables in the "variables" map. The endpoint response is available in the "response" variable as string. ie:
The script supports two modes:
The first example is in Plain Text mode, let's create a custom code to process a reply that simply returns the request data:
echo 'variables["sample_var1"] = str(request.header_string) + "\n\n" + str(request.content)
data=data.replace("{1}",variables["sample_var1"])' | base64 -w0
The output is:
dmFyaWFibGVzWyJzYW1wbGVfdmFyMSJdID0gc3RyKHJlcXVlc3QuaGVhZGVyX3N0cmluZykgKyAiXG5cbiIgKyBzdHIocmVxdWVzdC5jb250ZW50KQpkYXRhPWRhdGEucmVwbGFjZSgiezF9Iix2YXJpYWJsZXNbInNhbXBsZV92YXIxIl0pCg==
Since this is a plain response, and not a json response, we need the output from the base64 command for the response. In this example our response is all that the custom code generates for the key {1}. Which means our entire response is actually {1}. Lets encode it:
echo '{1}' | base64 -w0
ezF9Cg==
The final step is to register an endpoint with our code that uses custom code to replace '{1}' from our plain text response:
curl -X POST -H'Content-Type: application/json' -d'
{
"endpoint": "/echo",
"method": "post",
"header":"HTTP/1.1 200 OK\nDate: Fri, 20 June 2008 20:40:34 GMT\nServer:SING\nX-Powered-By: emilio\nConnection:close\n",
"replaceKeys":[{"key":"1","type":"custom","value":"dmFyaWFibGVzWyJzYW1wbGVfdmFyMSJdID0gc3RyKHJlcXVlc3QuaGVhZGVyX3N0cmluZykgKyAiXG5cbiIgKyBzdHIocmVxdWVzdC5jb250ZW50KQpkYXRhPWRhdGEucmVwbGFjZSgiezF9Iix2YXJpYWJsZXNbInNhbXBsZV92YXIxIl0pCg=="}],
"response": "ezF9Cg=="
}' http://localhost:2501/register
Lets test it:
curl -X POST -H'Content-Type: application/json' -d'Hola mundo' http://localhost:2501/echo
In this example we will use all possible key replacements:
curl -X POST -H'Content-Type: application/json' -d'
{
"endpoint": "/test",
"method": "post",
"header":"HTTP/1.1 200 OK\nDate: Fri, 20 June 2008 20:40:34 GMT\nServer:SING\nX-Powered-By: emilio\nConnection:close\nContent-Type: application/json\n",
"replaceKeys":[{"key":"1","type":"postParam","value":"firstpostparam"},
{"key":"2","type":"postParam","value":"secondpostparam"},
{"key":"3","type":"counter","value":"internalCounter1"},
{"key":"4","type":"randomInt","value":"0-65535"},
{"key":"5","type":"randomUUID","value":""},
{"key":"6","type":"custom","value":"dmFyaWFibGVzWyJoZWxsbyJdPSJIZWxsbyBXb3JsZCIKZGF0YT1kYXRhLnJlcGxhY2UoIns2fSIsdmFyaWFibGVzWyJoZWxsbyJdKQo="}],
"response": {
"firstPostParam": "{1}",
"secondPostParam": "{2}",
"myCounter": "{3}",
"firstPostAgain": "{1}",
"randomInteger":"{4}",
"randomUUID":"{5}",
"customCode":"{6}"
}
}' http://localhost:2501/register
Now that you have configured an endpoint, test if it works:
curl -v -X POST http://localhost:2501/test -d "firstpostparam=myvalue1&secondpostparam=myvalue2"
it should return the response with the parameters {x} replaced by the replace keys.
- Plain text responses MUST be encoded in base64. Read the "Redirect" example to see the fastest way to do it (the script already includes code to encode strings).
- replaceKeys is NOT required. If you don't specify it, the server will always return the static response you sent.
- response is NOT required. If you don't specify it the header will be returned.
- Be careful when you write your own response parser, you may break the reply. Try to double check your python code.
- The "custom" code is run after applying all other key replacements to the response.
- You can get URL params by accessing "request.params" inside your custom code
- You can share variables between each request, just store them in the dictionary "globalVars"
- Headers are stored in request.headers, and a plain text version is easily accesible with request.header_string
- The original contents of the request can be accessed with request.content
Copyright 2018 Emilio Moretti <emilio.morettiATgmailDOTcom> This program is distributed under the terms of the GNU Lesser General Public License.