A middleware that can transform, modify and forward requests based on pre-defined configuration. It allows you to modify your client request such as add, modify, or delete key-value, transform your request into JSON or XML and send the response back to the client. Execute Request configuration as a serial or parallel request
- Create a project folder inside configures folder. Take a look inside configures.testing/test-1.
- Inside a project folder create file configure.json, base.json, serial/parallel.json. configure.json can be renamed to anything.
- Create src/.env file (see src/.env.example file).
- Specify the path to the configures directory in .env (see src/.env.example file) .
See configures.testing directory structure for examples.
- Create configure directory, along with projects and configuration file, and router.json
- Specified your configure directory location in env
- Change working directory to
src
and run :
go build -o ./build/go-single-middleware ./cmd/.
- Run the program :
./build/go-single-middleware
- Create docker network called
proxy_middleware_net
by running :docker network create --driver bridge proxy_middleware_net
- Check if docker network have been created by running
docker network ls
: - Change working directory to where
src
located - Run
docker-compose build
- Run
docker-compose up
- Check if container have been assigned to network
proxy_middleware_net
by runningdocker network inspect proxy_middleware_net
- run
docker run -d --name='proxy-middleware' -p 8000:8888 dannydirect/tinyproxy:latest ANY
- Make sure that proxy-middleware is running :
- Configure postman proxy, by setting
proxy server
to0.0.0.0
andproxy port
to8000
:
- Check your container name and router
- To make a request, just enter url
http://<container name>/<path>
and hitsend
. Make sure containerproxy-middleware
is running and postman proxy settings have been set up.
{
"project_max_circular" : 10,
"circular_response" : {
"status_code" : 508,
"adds" : {
"body" : {
"message" : "Circular request",
"error" : "circular request detected"
}
}
}
}
Specify maximal number of circular request. This can be happen if configure-1 refer to configure-2 but configure-2 refer to configure-1.
Specify response to be returned if circular request has reached project_max_circular.s
In order to make request to this middleware, take a look inside configures.testing/router.json.
- path : Client to middleware endpoint.,
- project_directory : Project directory path relative to router.json,
- type : Make a serial or parallel request. The default value is serial if value is empty. Middleware will read related files (serial/parallel.json)
- method : Client to middleware request method.
Available values are- GET
- POST
- PUT
- DELETE
If you want to use path parameter from Client to middleware, you can use /:key.
For example, if middleware make a request with POST method to middleware at http://localhost:8000/smsotp/generate/25 for project smsotp, and then make a request from middleware to destination as a serial request :
[
{
"path" : "/smsotp/generate/:smsId",
"project_directory" : "smsotp",
"type" : "serial",
"method" : "POST"
}
]
Execute request sequentially. This json structure accept list of configures. for example:
{
"configures": [
{
"file_name": "test-1_configure-0.json",
"alias": "$configure_test-1",
"failure_response": {
"status_code": 500,
"transform": "ToJson",
"adds": {
"body": {
"error_message": "Request Logic error or there is something error"
}
}
},
"c_logics": []
}
]
}
Specify configure file name
Specify alias for configure file name. Must contain prefix $configure
Specify response if all logic fail
Accept list of json logic structure, based on https://jsonlogic.com/operations.html for example :
{
"rule": {
"==": [
"$configure_test-3_2--$request--$query[movie_id]",
550
]
},
data : null,
"response":null,
"next_success : null,
"next_failure": null,
"failure_response : null
}
Json logic operator/rule.
Json logic data.
Return response if logic is true.
return response if logic is false.
specify configure alias to be processed if logic is true. Response must be null.
specify configure alias to be processed if logic is false. Response must be false.
Execute request simultaneously. See example configures.testing/test-6.3 .
response to be returned when all logic is fail.
List of configuration file.
configure file name.
configure alias. Must contain prefix $configure.
check logic after all parallel request processed.
For each configure file in your project directory, it represents a request.
In order to forward your request, the middleware need to know the destination url and destination path.
- Specify destinationUrl in configure file
- Specify destinationPath in configure file
- The final endpoint is : destinationURL + destinationPath
You must specify your request method for key method in configure file. The following values are available : (UPPERCASE) :
- GET
- POST
- PUT
- DELETE
You can transform your request to JSON or XML. By default, the middleware will transform your request to JSON format. You can specify your request format for key transform in configure file. The following values are available :
- ToJson to transform your request to JSON format.
- ToXml to transform your request to XML format
If a request/response don't have any wrapper for the body and you want to convert it to xml,
it automatically wrap your request with such that (body)
, because this middleware use package clbanning/mxj,
For example if you send an empty request to the middleware, and your configuration for request like below and you want to transform it to XML :
"request": {
"destinationPath": "/",
"destinationUrl": "http://localhost:3001",
"transform": "ToJson",
"logBeforeModify" : "",
"logAfterModify" : "",
"adds": {
"header": {
},
"body": {
"name" : "nicholas",
"last_name": "anthony"
},
"query": {
}
},
"modifies": {
"header": {
},
"body": {
},
"query": {
}
},
"deletes": {
"header": [
],
"body": [
],
"query": [
]
},
c_logics : [],
},
The middleware will add name and last_name to the body, but because the request don't have any wrapper element, your request will be :
<doc>
<last_name>anthony</last_name>
<name>nicholas</name>
</doc>
If you want to pick the value from this configure, for example name, you have to mention the doc like $body[doc][name] .
Middleware will do addition, modification, deletion sequentially. Request modification can be performed for header, body, and query.
You can add key-value to your request, by specify key and value. You can also add key-value to a nested object by using ".(dot)", or directly add a nested object. If the object is not exist, the middleware will create it for you. In this example, we will add key id , name and favourite_cars property to a nested object user to a request body using dot syntax, add nested object address.
"adds": {
"header": {
},
"body": {
"id" : "123",
"user.name" : "nicholas",
"user.favorite_cars": [
"honda",
"fiat",
"toyota",
"ferrari"
],
"address" : {
"city" : "bandung",
"province" : "west java"
}
},
"query": {}
},
####4.2 modify You can modify your request by specify key-value pair in modify . In order to modify a certain key from your request, key must already existed* in your request. The following examples shows that we want to modify id and modify name from nested object user.
"modifies": {
"header": {
},
"body": {
"id" : 456,
"user.name" : "anthony"
},
"query": {}
},
Note : key-value for request header and query cannot be a nested object
To delete keys from your request, you can specify it in deletes. The following example shows that we want to delete name property from nested object user, and we want to delete id.
"deletes": {
"header": [],
"body": [
"id",
"user.name"
],
"query": []
}
Note : You can also delete an entire object, for example, replace user.name with user, you will delete object user from your request.
Check logic before sending request. If logic is false, you can specify failure_response to return response or next_failure execute next config. In serial request, if failure_response and response not specified, middleware will return serial failure_response for current processed configure that has been specified in serial.json. In Parallel request, middleware will return failure_response that has been specified in parallel.json. Middleware will not send any request. If logic is true, you can specify response to return response or next_success to execute next config. If response and next_success not specified, middleware will send request.
"c_logics": [
{
"rule": {
"and": [
{
"==": [
"$configure_test-4_0--$request--$query[movie_id]",
550
]
},
{
"==": [
"$configure_test-4_0--$request--$query[movie_id2]",
384018
]
}
]
},
"data" : null,
"response" : null,
"next_success" : "$configure_test-4_1",
"next_failure" : null,
"failure_response" : null
}
]
You can modify response from each request but only for body and header, the rules are the same like request modification.
Note : key-value for response header cannot be a nested object
To pick a value between each configure, you must consider from which configure you want to pick the value, whether your value located in :
- request header, body, query, or path parameter
- response body or header
For example, if our configure1.json want to pick name from nested object user which located in response body in configure0.json, we can write :
$configure0.json--$request--$body[user][name]
If you want to pick a value from array, for example if the request from configure0.json has cars in the nested object user and the value is ["toyota","honda","hyundai"], then we can pick toyota like the following code :
$configure0.json--$request--$body[user][cars][0]
Notice that each section is separated by double dash (--). That's why you can't use double dash for configure file name.
- If you use serial route, you can only pick the value from previous configure, you can't pick the value from configure2.json the middleware execute the request sequentially. For example, you can pick a value for configure1.json from configure0.json request or response, you can't pick a value from configure3.json. This is because configure0.json is the first index in configures directory, following by configure1.json, and last configure3.json.
Remember that the order of configure-n.json file in configures directory is really important for serial route
- If you use parallel route, you can't pick the value between each configure because the middleware execute the request simultaneously. For example, you can't pick a value for configure1.json from configure0.json request or response.
You can log header, body, query, path parameter from each configure file by specifying value for keys :
- logBeforeModify : This will log a value before change/modify request/response.
- logAfterModify : This will log a value after change/modify request/response.
Following values are available:
- $body
- $header
- $query
- $path
Or if you want to log specific value, you can specify it like this: $body[user][name].
Example :
"logBeforeModify" : "$body", // this will log the whole body before doing any change.
"logAfterModify" : "$body[user][name]" // this will log name from object user after doing change.