A "Location" is a part of the site which matches specific attributes in the incoming request - it can be e.g. a specific hostname (virtual host), it can be based upon URL path, or even user ID or group.
For a particular location you specify how the gateway should react - should it modify the request or responses ? should it add/remove headers or cookies, and should it forward/proxy the request to one of the configured Destinations or should it respond with a specific response or a dynamic one created by a script.
Refer to Locations in the concepts guide for more information about what locations are.
Locations are stored as separate JSON objects in the locationsarray in the gateway JSON configuration.
{ "session": {}, "destinations": ], "locations": [ { "location.enabled": true, "location.enabled": true, "plugin": {}, "session.needed": false, "response.compress": true, "response.redirect": "https://%{HTTP_HOST}:8443%{PATH_WITH_QUERY}", "name": "Unsecured requests", "action": "respond", "description": "Redirect http to https", "conditions": [ { "values": ["http"], "type": "scheme" }, { "deny": true, "values": [ "127.0.0.1", "localhost", "::1", "0:0:0:0:0:0:0:1" ], "type": "remoteip" } ], "response.status": 307, "cookiesnapper": {} }, { "name": "OpenID Connect Google", "description": "OpenID Connect authorization code flow example using Google", "conditions": [{ "deny": false, "values": ["/openid"], "type": "path" }], "authentication": { "plugins": ["io.ceptor.authentication.AuthenticatorOpenIDConnect"], "openidconnect": { "response.contenttype": "text/html", "identityprovider.name": "google", "authenticationplugin": 48, "redirecturl": "https://%{HTTP_HOST}/openid", "scope": "openid email profile", "authorize.url": "https://accounts.google.com/o/oauth2/auth", "response.status": 200, "response.content": "<html>\n<head><title>Success<\/title>\n<body>\n<h1>Success<\/h1>\nWelcome %{statevariable:email} - authentication succeeded using google.\n<\/body>\n<\/html>", "parameters": "access_type=online", "client.id": "371213948273-79eceu24cm64ft69pln0hk2lfapok1bq.apps.googleusercontent.com" } } }, { "name": "OpenID Connect Microsoft", "description": "OpenID Connect authorization code flow example using Microsoft", "conditions": [{ "deny": false, "values": ["/openidmicrosoft"], "type": "path" }], "authentication": { "plugins": ["io.ceptor.authentication.AuthenticatorOpenIDConnect"], "openidconnect": { "response.contenttype": "text/html", "identityprovider.name": "microsoft", "authenticationplugin": 48, "redirecturl": "https://%{HTTP_HOST}/openidmicrosoft", "scope": "openid email profile", "authorize.url": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", "response.status": 200, "response.content": "<html>\n<head><title>Success<\/title>\n<body>\n<h1>Success<\/h1>\nWelcome %{REMOTE_USER} - authentication succeeded using Microsoft Online.\n<\/body>\n<\/html>", "client.id": "317190f9-efec-4307-beb9-7f8380a8ae16" } } }, { "authorization": { "roles": [], "authorization.script": "state.agent.logoff(state.id);\ntrue;" }, "response.contenttype": "text/html", "content.preload": false, "plugin": {}, "session.needed": true, "session.afterconditionsmatch": false, "name": "Logoff", "description": "Logs off the session", "action": "respond", "conditions": [{ "deny": false, "values": ["/logoff"], "type": "path" }], "response.status": 200, "response.content": "<html><body>You are now logged off.<\/body><\/html>", "cookiesnapper": {} }, { "response.contenttype": "text/html", "plugin": {}, "session.needed": true, "name": "WebSSO", "description": "WebSSO / ADFS Example", "action": "respond", "response.reason": "OK", "response.status": 200, "response.content": "<html>\n<body>Hello... %{REMOTE_USER}\n<\/body>\n<\/html>", "cookiesnapper": {}, "conditions": [{ "deny": false, "values": ["/adfs"], "type": "path" }], "authentication": { "websso": { "response.contenttype": "text/html", "identityprovider.name": "%{script}var name=state.getQueryOrPostParam(\"idpname\");\nif (name === null) name = 'microsoft';\nname;", "redirecturl": "%{REQUEST_URL}", "serviceprovider.name": "%{script}state.getQueryOrPostParam(\"spname\");", "failure": { "response.contenttype": "text/html", "action": "respond", "response.status": 403, "response.content": "<html><body>Authentication failed<p/>\nDetails:<\/br>\n<pre>\n%{htmlencode:EXCEPTION_LOG}\n<\/pre>\n<\/body><\/html>" }, "response.status": 200, "response.content": "<html><body>Success %{REMOTE_USER}<\/body><\/html>", "federation.enabled": true }, "plugins": ["io.ceptor.authentication.AuthenticatorWebSSO"] } }, { "content.preload": false, "description": "Every single request", "request.concurrent.max": 0, "cookiesnapper": { "classifier": "%{HTTP_HOST}", "pattern": "JSESSIONID" }, "request.queue.size": 10000, "valid.methods": "GET|POST|OPTIONS|HEAD", "noauthentication.for.options": false, "authorization": { "noauthorization.for.options": false, "roles": [], "server.identifier": "none" }, "proxy.destination": "demoapp", "request.headers": [ { "name": "X-Forwarded-Proto", "value": "%{HTTP_SCHEME}" }, { "name": "X-Forwarded-For", "value": "%{REMOTE_ADDR}" }, { "name": "X-Forwarded-Port", "value": "%{REMOTE_PORT}" }, { "name": "X-Forwarded-Server", "value": "%{SERVER_NAME}" } ], "plugin": {"classifier": "%{HTTP_HOST}"}, "request.persecond.max": 0, "response.maxbytes.persecond": 0, "urlrewrite": [{ "newurl": "/secret/$1", "last": true, "pattern.flags": "CASE_INSENSITIVE", "decode.before.match": true, "name": "TOPSECRET to secret", "pattern": "^/TOPSECRET/(.*)", "redirect": false, "clear.query.params": false, "conditions": [{ "deny": false, "values": [ "localhost*", "{regex:IGNORE_CASE}LoCaLhOsT.*" ], "type": "host" }] }], "session.needed": false, "response.compress": true, "name": "All requests", "response.cookies": [{ "path": "/stuff", "discard": false, "name": "IWasHere", "httponly": true, "samesite": lax, "secure": true, "value": "%{GEOIP_ISP}" }], "action": "continue", "response.headers": [ { "name": "Via", "value": "ceptor.io" }, { "name": "Server", "value": null }, { "name": "Location", "value": "%{rewrite:responseheader:location;\"http\\:\\/\\/(.*)$\";\"CASE_INSENSITIVE\";\"https://$1\"}" } ], "conditions": [], "request.cookies": [ { "name": "sessionid", "value": null }, { "name": "sslsessionid", "value": null } ] }, { "request.attributes": [{ "name": "NotAGif", "value": "true" }], "plugin": {}, "response.hooks": [ { "expected.response.status": "404", "respond": true, "response.headers": [{ "name": "X-Content", "value": "WasNotFound" }], "response.status": 404, "response.reason": "Sorry, not found", "response.contenttype": "text/plain", "response.content": "Oh no, I did not find that" }, { "expected.response.status": "401", "respond": false, "response.status": 302, "response.redirect": "https://somewhere.else", "script": "%{script}// Example javascript that simply sends the response configured in the response hook\r\n\r\ncontext.gateway.sendResponse(context, context.currentResponseHook.response);" } ], "session.notvalid.action": "continue", "url.validator": { "verify.encoding": true, "verify.fullurl": true, "maxlength": 32768, "query.key.maxlength": 1024, "query.value.maxlength": 8192, "enabled": true, "authority.regex": null }, "session.needed": false, "name": "All requests except jpg,png,gif,css", "action": "continue", "conditions": [ { "values": ["*"], "type": "path" }, { "deny": true, "values": ["*.jpg|*.png|*.gif|*.css"], "type": "path" } ], "param.validator": { "verify.pathparams": true, "verify.params": [{ "value.lowercase": true, "key.lowercase": true, "value": "*abc*1", "key": "test*" }], "failure": { "response.contenttype": "text/html", "action": "respond", "response.headers": [], "response.reason": "Invalid parameter", "response.status": 400, "response.content": "<html><body><h1>Invalid parameter<\/h1><\/body><\/html>" }, "verify.postparams": false, "verify.params.required": true, "verify.params.extra.allowed": true, "verify.queryparams": true }, "cookiesnapper": {}, "authentication": { "ntlm": { "authenticationplugin": 35, "failure": { "response.contenttype": "%{script:if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'application/json') 'application/json'; else 'text/html';}", "action": "respond", "response.reason": "Invalid userid/password", "response.status": 403, "response.content": "%{script:if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'application/json') '{\"error\":\"access.denied\"\\}'; else '<html><head><title>No access<\/title><body><h1>Invalid userid/password<\/h1><\/body><\/html>';}" }, "required": false, "allow.anonymous": true }, "plugins": [ "io.ceptor.authentication.AuthenticatorSSLClientCert", "io.ceptor.authentication.AuthenticatorBasicAuth" ], "spnego": { "authenticationplugin": 26, "failure": { "response.contenttype": "%{script:if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'application/json') 'application/json'; else 'text/html';}", "action": "respond", "response.reason": "Invalid userid/password", "response.status": 403, "response.content": "%{script:if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'application/json') '{\"error\":\"access.denied\"\\}'; else '<html><head><title>No access<\/title><body><h1>Invalid userid/password<\/h1><\/body><\/html>';}" }, "allow.ntlm.fallback": true }, "basicauth": { "authenticationplugin": 9, "failure": { "response.contenttype": "%{script:if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'application/json') 'application/json'; else 'text/html';}", "action": "respond", "response.headers": [{ "name": "WWW-Authenticate", "value": "Basic realm=\"ceptor.io\"" }], "response.reason": "Invalid userid/password", "response.status": 401, "response.content": "%{script:if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'application/json') '{\"error\":\"access.denied\"\\}'; else '<html><head><title>No access<\/title><body><h1>Invalid userid/password<\/h1><\/body><\/html>';}" }, "realm": "ceptor.io", "required": false }, "ssl": { "authenticationplugin": 18, "failure": { "response.contenttype": "%{script:if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'application/json') 'application/json'; else 'text/html';}", "action": "respond", "response.reason": "Invalid client cert", "response.status": 401, "response.content": "%{script:if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'application/json') '{\"error\":\"access.denied\"\\}'; else '<html><head><title>No access<\/title><body><h1>Invalid client certificate<\/h1><\/body><\/html>';}" }, "required": false } }, "ip.restriction": { "ranges": [ { "values": [ "127.0.0.1-127.0.0.255", "::1" ], "name": "local" }, { "values": ["192.168.1.0/24"], "name": "intranet" }, { "values": ["{file}${portalprotect.home}/config/iprange1.txt"], "name": "range1" } ], "allowchange": true, "action.invalid": { "response.redirect": "/invalid?originalUrl=%{urlencode:REQUEST_URL}", "action": "respond", "response.reason": "Invalid IP", "response.status": 302 }, "ip.address.maxcount": 32, "geoip.type": "complex", "geoip.distance": 100, "geoip.complexrules": [ "ip1=ip2", "country1=country2&country2=\"DK\"", "distance=300" ], "script": "if (input == '127.0.0.1') true; else false;" } }, { "plugin": { "response.wrapper.script": "%{file}/responsedumper.js", "response.wrapper.class": "io.ceptor.gateway.plugin.ResponseDumper", "request.wrapper.class": "io.ceptor.gateway.plugin.RequestDumper", "XXXrequest.wrapper.script": "%{file}/requestdumper.js" }, "session.needed": false, "name": "JSP response dumper", "conditions": [{ "values": ["*.jsp"], "type": "path" }], "cookiesnapper": {} }, { "proxy.destination": "google", "plugin": {}, "urlrewrite": [{ "newurl": "https://www.google.com/search?q=$1", "last": true, "decode.before.match": true, "name": "googl", "pattern": "^/search/(.*)$" }], "session.needed": false, "roles": ["pp_everyone"], "name": "Google", "action": "proxy", "conditions": [{ "values": ["/search*"], "type": "path" }], "cookiesnapper": {} }, { "authorization": { "failure": { "response.contenttype": "%{script:if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'application/json') 'application/json'; else 'text/html';}", "action": "respond", "response.reason": "No access", "response.status": 403, "response.content": "%{script:if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'application/json') '{\"error\":\"access.denied\"\\}'; else '<html><head><title>No access<\/title><body><h1>403 No Access<\/h1><\/body><\/html>';}" }, "roles": [ "staff", "pp_identifiedusers" ], "server.identifier": "default" }, "request.headers": [ { "name": "authorization", "value": null }, { "name": "x-user", "value": null }, { "name": "x-forwarded-server", "value": null }, { "name": "user-agent", "value": null }, { "name": "Host", "value": "ekstrabladet.dk" }, { "name": "Referer", "value": null } ], "name": "Secret Destination", "action": "continue", "locations": [ { "proxy.destination": "ekstrabladet", "name": "EB", "action": "proxy", "conditions": [{ "values": ["localhost*"], "type": "host" }] }, { "proxy.destination": "google", "name": "Google", "action": "proxy", "conditions": [] } ], "conditions": [ { "ignorecase": true, "values": [ "/secret/*", "/secret", "{regex}^/verysecret.*$" ], "type": "path" }, { "values": ["*"], "type": "host" } ], "request.cookies": [{ "name": "pp_jsessionid", "value": null }], "ip.restriction": { "ranges": [{ "values": ["192.168.1.0/30"], "name": "Internal" }], "allowchange": false }, "authentication": { "plugins": [ "io.ceptor.authentication.AuthenticatorScript", "io.ceptor.authentication.AuthenticatorForms", "io.ceptor.authentication.AuthenticatorBasicAuth" ], "basicauth": { "realm": "ceptor", "required": false }, "forms": { "redirect": { "response.redirect": "/login.jsp", "action": "respond" }, "authenticationplugin": 9, "failure": { "response.contenttype": "%{script:if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'application/json') 'application/json'; else 'text/html';}", "action": "respond", "response.reason": "Invalid userid/password", "response.status": 403, "response.content": "%{script:if (state.httpExchange.getRequestHeaders().getFirst('Content-Type') == 'application/json') '{\"error\":\"access.denied\"\\}'; else '<html><head><title>No access<\/title><body><h1>Invalid userid/password<\/h1><\/body><\/html>';}" }, "required": false }, "script": { "content.preload": false, "authentication.script": "authenticate();\r\n\r\nfunction authenticate() {\r\n // If already authenticated, just continue\r\n if (state.agent.isLoggedOn(state.id))\r\n return 'CONTINUE';\r\n \r\n try {\r\n var user = state.httpExchange.getRequestHeaders().getFirst('X-User');\r\n var pass = state.httpExchange.getRequestHeaders().getFirst('X-Password');\r\n if (user === null) {\r\n user = state.httpExchange.getQueryParameters().get('X-User').getFirst();\r\n }\r\n if (pass === null) {\r\n pass = state.httpExchange.getQueryParameters().get('X-Password').getFirst();\r\n }\r\n \r\n if (user === null || pass === null) {\r\n // Ignore if user or password is not supplied - making this type of authentication optional\r\n return 'CONTINUE';\r\n } else {\r\n state.trace.trace('About to logon from script with user: ' + user);\r\n // 9 is authentication plugin type\r\n state.agent.logon(state.id, 9, user, pass, null);\r\n return 'SUCCESS';\r\n }\r\n } catch(err) {\r\n state.gateway.sendAndLogError(state, 401, 'Authentication Required', err);\r\n return 'RESPOND';\r\n }\r\n}" } } }, { "proxy.destination": "demoapp", "roles": ["pp_everyone"], "name": "Local", "action": "proxy", "conditions": [{ "values": ["/*"], "type": "path" }], "request.cookies": [{ "name": "ppSessionId", "value": "%{REQUEST_ID}" }] }, { "response.contenttype": "text/html", "#description": "Deny access to everything, by default if no other rule is matching", "name": "Default", "action": "respond", "response.headers": [{ "name": "X-Access", "value": "Denied" }], "response.reason": "No access", "conditions": [{ "values": ["/*"], "type": "path" }], "response.status": 403, "response.content": "<html><head><title>No access<\/title><body><h1>403 No Access<\/h1><\/body><\/html>" } ], "gateway": {}, "listen": [] } |
Each location is stored in its own JSON object within the locations array.
You can add/remove and reorder Locations - they are processed in the order they appear. When the conditions for a location matches the request, the location will be processed - if its action is RESPOND or PROXY no further locations will be processed.
If a matched location has any nested locations defined, they will be processed before going down to the next location in the list.
When you press Add to add a new location, you get this prompt:
You should enter the unique name of the location, and optionally a description of it - it is often useful to enter a reason for its existence here - even if it might be obvious at first it is likely not so obvious in a few years.
The configuration for each specific location looks like the screenshot below.
It has many sections below it - note that they are marked with a blank circle if no values are defined for that particular section, and a cog if something is defined for this section. This makes it easy to see if you need to look at a particular session when going through the configuration to view the settings for a particular location.
Name of location - used for logging/tracing and diagnostics
Default: none, a unique name is required
JSON key: name
Description
Description of this location
Default: blank
JSON key: description
If unchecked, This location is ignored and not processed - it is treated like it did not exist.
Default: true
JSON key: location.enabled
If unchecked, no session is needed, so no request ID, session ID etc. will be available for this location unless a previous location has retrieved the session. Note that authentication and IP checking will not be done if there is no session present.
You can turn this off if you want anonymous, unauthenticated access to parts of your site, e.g. if you have a publicly available static part that you have no interest in authenticating users, doing IP checking etc. - this will ensure as fast performance as possible, since the overhead is kept to a bare minimum. |
JSON key: session.needed
Default: true
If checked, and if session is needed, a session will not be established before conditions are checked, so it will only be done if conditions match. Note that some conditions, such as those on user or group or some scripts/macros require a session so they will not work.
Default: false
JSON key: session.afterconditionsmatch
If checked, this allows you to override the session settings per location - in that case, you will get a new screen as child of the location where you can specify session resolvers and settings. Note that unless "Session is needed" is checked, this option will not have any effect.
Also, bear in mind that once a location has obtained a session once during request processing, any subsequent resolvers are ignored since the session is already available.
JSON key: session.override
Default: false
If checked, request content will be preloaded into memory before processing this location this is required (and automatically enabled if conditions contain postparam values) for processing POST'ed request content.
Using this allows you to access request body in plugins / scripts for this or subsequently processed locations. Note that it affects performance slightly, and it requires increased memory use to store the request contents until the request is done.
Default: false
JSON key: content.preload
Valid HTTP methods - default is OPTIONS|HEAD|GET|POST, you can specify a pattern with wildcards or use {regex} prefix to create regular expression match. If the request method does not match this pattern, HTTP error 405 is immediately sent back.
Default: OPTIONS|HEAD|GET|POST
JSON key: valid.methods
Action to take for this location, can continue to next location, respond by writing a response back to the browser, proxy to a destination server or serve static resources.
Default: continue
JSON key: action
Destination to forward request to, if action is proxy.
Default: blank
JSON key: proxy.destination
If set, and client indicates support for it (gzip/deflate) then responses sent to the client are compressed unless the destination server has already done so itself.
Default: true
JSON key: response.compress
Can be used to limit the number of concurrent requests, or requests per second for this location.
Qualifier for limiting requests per second or concurrent requests - if not set, those limits apply for all requests for the given location, but if set, limits can be specified per IP address, per client ID or any other parameter you wish to use as a qualifier.
As an example, you can use %{REMOTE_ADDR}
to limit requests per client IP, or e.g. %{statevariable:client_id}
to apply limits to the client_id attribute within the session.
Note that limits and qualifiers are per location, so any expression you choose will only affect this location and not others.
Default: Blank, no value
JSON key: requestlimit.qualifier
Maximum number of requests per second, set to 0 for no limit.
Default: 0 (no limit)
JSON key: request.persecond.max
Maximum number of concurrent requests for this location - any additional requests will be queued up, or 0 for no limit.
Default: 0 (no limit)
JSON key: request.concurrent.max
If too many concurrent requests, this is the maximum number of requests that can be queued up.
If number of requests in the queue exceeds this limit, new ones will be denied with HTTP 513 to indicate to the client that the server is overloaded with concurrent requests and its queue is full.
Default: 1000
JSON key: request.queue.size
If set to nonzero, limits the number of response bytes sent per second (per connection) to the client.
Default: 0
JSON key: response.maxsize.persecond
Script to execute when this location is triggered.
Whenever this location is hit, this script will be executed which provides a simple method of adding functionality you would otherwise need to do in a pipeline or authorization/authentication script.
This is a useful place to e.g. manipulate with the contents of the users' session and/or the request before further processing is done.
Default: none
JSON key: location.script
See Pipelines and Tasks for more information about pipelines.
Specify pipeline name. A pipeline allows advanced functionality, such as calling multiple remote services, validating JSON, running scripts etc. If a name of an existing pipeline is specified here, it is called immediately after processing limits.
A task within a pipeline might elect to send a response, or proxy a request - and in that case the action in this location has no effect - request processing will then never be given back to this location. |
JSON key: pipeline
Default: none.
If action is set to RESPOND, then a response will be sent to the client with the information below. Note that the HTTP Response headers and cookies will also be added, if any are configured.
Note that Scripts and Macros can be used to specify these values dynamically based upon request content.
Specify the name of a "canned" response here to reuse it - when set, the response sent back will be the one defined in the canned response - if any other values are specified here, HTTP response code, reason etc. then these values overwrite what was specified in the canned response. Any headers defined will complement the ones specified for the canned response.
Default: none
JSON key: response.name
HTTP Response code to send back to client.
Default: 500
JSON key: response.status
HTTP response reason text
Default: No additional information
JSON key: response.reason
Response Redirect Location URL - if set, a redirect will be sent instead of a normal response, the Location header in the response will be set to this value.
Default: none
JSON key: response.redirect
HTTP Response content-type
Default: none
JSON key: response.contenttype
Response body contents
Default: none
JSON key: response.body
Configuration is stored in the JSON object cookiesnapper.
Note that CookieSnappers can be configured both for locations and destinations - they serve the exact same functionality, but in some cases it is easier to define them on destinations so they have effect for all locations proxying to a certain destination - in other cases you only want this enabled for some locations - e.g. if you only want this for certain browsers or other things your location conditions can decide upon. |
Pattern defining which cookies to remove from the response and place into the session. Any cookies matching this pattern will be moved from the response to the session, and added on future requests.
Default value: blank
JSON key: pattern
Classifier to use - here you can use %{} variables, such as %{HTTP_HOST} or %{script:xxxx} to specify the classifier or scope to restrict these cookies too.
The classifier can ensure that the cookies are not forwarded on all requests, but only where the next request has the same classifier - so if it is e.g. set to %{HTTP_HOST} then the cookie will only be added to future requests, if these request has the exact same hostname as this one.
If the classifier is left as "default" then if the next request has a different hostname, e.g. app2.mydomain.com then the cookie will be added to the request again, which is usually what you want.
Default value: "default"
JSON key: classifier
Plugins are java or script code that can process request or response bodies - they can e.g. transform contents from one format to another, e.g. add encryption, verify signatures etc.
Plugin configuration is stored in the JSON Object plugin within the location JSON Object.
Java class implementing ConduitWrapper<StreamSourceConduit> to process request body - see Plugins#JavaRequestWrapper for more information.
Default: none
JSON key: request.wrapper.class
Java class implementing ConduitWrapper<StreamSinkConduit> to process response body - see Plugins#JavaResponseWrapper for more information.
Default: none
JSON key: response.wrapper.class
Script that processes request body - see Plugins#ScriptRequestWrapper for more information.
Default: none
JSON key: response.wrapper.script
Script that processes response body see Plugins#ScriptResponseWrapper for more information.
Default: none
JSON key: response.wrapper.script
If "Override global session settings" is checked, you can configure the session settings specifically for this location. The same fields as in the global session configuration are available. JSON configuration is stored in a JSON Object called "session" inside the location JSON.
If a session is not valid, you can specify what action to take - and decide to either respond/redirect to another page, or continue with a new anonymous session.
These configuration entries are stored in the JSON Object action.session.notvalid within the location.
Action to take for this location, if request had an invalid or timed out session ID. continue=go on without authenticating, respond=respond with configured response or redirect
If action is set to RESPOND, then a response will be sent to the client with the information below.
Note that Scripts and Macros can be used to specify these values dynamically based upon request content.
Specify the name of a "canned" response here to reuse it - when set, the response sent back will be the one defined in the canned response - if any other values are specified here, HTTP response code, reason etc. then these values overwrite what was specified in the canned response. Any headers defined will complement the ones specified for the canned response.
Default: none
JSON key: response.name
HTTP Response code to send back to client.
Default: 500
JSON key: response.status
HTTP response reason text
Default: No additional information
JSON key: response.reason
Response Redirect Location URL - if set, a redirect will be sent instead of a normal response, the Location header in the response will be set to this value.
Default: none
JSON key: response.redirect
HTTP Response content-type
Default: none
JSON key: response.contenttype
Response body contents
Default: none
JSON key: response.body
Response headers can also be added to the response, if any are specified, they are in an JSON array called response.headers within the action.session.notvalid JSON object.
You can add headers by clicking "Add", then you get a popup where you can set the name and value of the header.
Once created, they are added to the JSON Array response.headers within the action.session.notvalid JSON object, as a new object with the attributes name and value set to the entered name and value.
List of conditions required to match for this location - if no conditions, all requests will match.
You can add/remove and move conditions up and down - they will be checked in the order listed.
Conditions are stored in the JSON array conditions within the location object.
When you add a new condition, you need to fill out this dialog:
When you edit each specific condition, you do it in this dialog:
Here, you can edit the type, name and add/remove/edit values - a condition can have multiple values.
Type of condition.
You can select between these types:
Default: none - must be selected.
JSON key: type
For some types, a name is required. For query/pathparam/postparam it is the name of the query parameter. For header, it is the name of the request header. For attribute it is the name of the request attribute. For GeoIP, it is one of [isp, organization, countrycode, countryname, city, postalcode, region]
Default: none
JSON key: name
Reverse the check, so if one of the values match, the condition is NOT met.
Default: false
JSON key: deny
If set, the attribute (e.g. path, query parmeter or username) will be converted to lowercase before being matched to one of the specified values.
Default: false
JSON key: lowercase
List of possible values that this condition can match. The value is a pattern, where wildcards can be used and you can separate multiple entries with | - if prefixed with {regex} you can use a regular expression, and you can use {uripath} to make wildcards match all characters except forward slash.
If the type is set to script then the value contains a script which will be executed to check for a match. Note that it is very important that this script performs extremely well since it will be executed for all requests and might risk blocking other requests.
Default: none
JSON key: values is an array of strings, where each string is a single value.
Configuration for response hooks are in the form of a JSON Array response.hooks
containing a number of JSON response hook objects inside a location.
Here, you can add Response Hooks, which are activated once the HTTP response header is read from a response proxied from the backend server. This gives you a chance to hook into the response and take another action, such as returning another response, changing headers or response code etc.
When adding an new Response Hook, you must type in the HTTP status code it should match - note that you can use wildcard characters to match, e.g. 302|307 or 3* or just 401
Response hooks are only triggered on responses coming back from requests having been proxied to backend servers. As locations are processed, response hooks are added to a list in the request context - ready for processing once the response is retrieved. A location's response hooks are always added to the beginning of this list - this makes it possible to create multiple response hooks for the same HTTP response codes, e.g. by adding generic handling first and then later override with more specialized handling for specific locations. |
Below is an example of editing a single response hook.
The HTTP response code that this hook is valid for - can contain wildcards or multiple status codes separated by pipe sign.
Default: none
JSON key: expected.response.status
Script to be executed once HTTP response header is read. This script can manipulate the contents of the headers and status code, or send another response instead.
The relevant variables in the context that can be used modified are:
/** This is meant for use by response hooks - The response status - only available after reading response headers */ public int proxyResponseStatusCode; /** This is meant for use by response hooks - The response headers read from the server we proxied to */ public HeaderMap proxyResponseHeaders; /** This is meant for use by response hooks - the connection to the server */ public ClientExchange proxyClientExchange; /** This is meant for use by response hooks - the currently executing response hook */ public Config.ResponseHook currentResponseHook; |
The script can modify the HTTP response code, or the headers before they are processed by the rest of the gateway - the script is called immediately after retrieving the response from the backend, before any other actions are done. The script can choose to create and send a response itself, or it can use the one defined in its response hook, by calling:
|
Default: none
JSON key: script
If checked, the defined response is sent instead of the response from the backend server, if not the response is defined and can be sent by the script, but it is not sent automatically.
Default: false
JSON key: respond
Specify the name of a "canned" response here to reuse it - when set, the response sent back will be the one defined in the canned response - if any other values are specified here, HTTP response code, reason etc. then these values overwrite what was specified in the canned response. Any headers defined will complement the ones specified for the canned response.
Default: none
JSON key: response.name
HTTP Response code to send back to client.
Default: 400
JSON key: response.status
HTTP response reason text
Default: No additional information
JSON key: response.reason
Response Redirect Location URL - if set, a redirect will be sent instead of a normal response, the Location header in the response will be set to this value.
Default: none
JSON key: response.redirect
HTTP Response content-type
Default: none
JSON key: response.contenttype
Response body contents
Default: none
JSON key: response.body
Response headers can also be added to the response, if any are specified, they are in an JSON array called response.headers within the individual response hook JSON object.
You can add headers by clicking "Add", then you get a popup where you can set the name and value of the header.
Once created, they are added to the JSON Array response.headers within the response hook JSON object, as a new object with the attributes name and value set to the entered name and value.
Configuration for URL validation is stored in the JSON object url.validator
Enable or disable this URL validator
Default: false
JSON key: enabled
If set, verifies that URL Encoding is valid.
Default: true
JSON key: verify.encoding
Max length of query parameter name, or 0 to disable validation.
Default: 1024
JSON key: query.key.maxlength
Max length of query parameter value, or 0 to disable validation.
Default: 8192
JSON key: query.value.maxlength
Max length of entire URL, or 0 to disable validation.
Default: 32768
JSON key: maxlength
If set (and if "Enable URL validation" is checked), verifies the full URL for validity using Apache URL Validator, this includes checking domain name for validity against whitelist of IANA validated top-level domains.
Default: true
JSON key: verify.fullurl
If specified, authority (first part of the url until the path starts) this pattern allows adding non IANA approved domain names, such as <b>.local</b> - here, you need a regular expression so make sure your expesssion only matches the minimum you need.
Default: null
JSON key: authority.regex
Parameter Validation allows you to validate path, POST and/or query parameters - you can use this to ensure that only valid characters are present in the parameters.
If you set the key to * and the value to
Then you can ensure that all input only contains alphanumeric characters or underscore - any other content and the validation fails and the failure action will be executed (which usually means returning an error message to the client). |
Parameter Validation configuration is stored in a JSON object called param.validator inside the location.
Determines if the specified parameters are required to be present in the request or not - if required, at least one parameter matching each specified key must be present or the request will fail. If not checked, the parameters are not required, but if they are present, they must have a value matching the pattern/regex in the value for the matching parameters.
Default: false
JSON Key: verify.params.required
If checked, additional parameters not matching the ones specified in the parameter list are allowed - these additional parameters will not have their value checked.
Default: true
JSON Key: verify.params.extra.allowed
If checked, query parameters are validated, otherwise they are ignored.
Default: true
JSON Key: verify.queryparams
If checked, POSTbparameters are validated, otherwise they are ignored.
Default: true
JSON Key: verify.postparams
If checked, path parameters are validated, otherwise they are ignored.
Default: true
JSON Key: verify.pathparams
Contains a list of valid parameter key/values which are used in validating the input parameters.
You can add new parameters, remove or edit existing ones - if editing you get this dialog:
JSON Key: verify.params - Contains an array of JSON Objects, each parameter object has these values;
Specifies what action to take if input parameter validation fails - usually you want to return an error response here.
JSON Configuration for this is stored within the failure JSON Object inside the param.validator object.
Action to take for this location, if parameter validation fails, Either respond=respond with configured response or redirect, or proxy=forward request to a configured destination.
Default: respond
JSON key: action
Specify the name of a "canned" response here to reuse it - when set, the response sent back will be the one defined in the canned response - if any other values are specified here, HTTP response code, reason etc. then these values overwrite what was specified in the canned response. Any headers defined will complement the ones specified for the canned response.
Default: none
JSON key: response.name
HTTP Response code to send back to client.
Default: 400
JSON key: response.status
HTTP response reason text
Default: No additional information
JSON key: response.reason
Response Redirect Location URL - if set, a redirect will be sent instead of a normal response, the Location header in the response will be set to this value.
Default: none
JSON key: response.redirect
HTTP Response content-type
Default: none
JSON key: response.contenttype
Response body contents
Default: none
JSON key: response.body
Response headers can also be added to the response, if any are specified, they are in an JSON array called response.headers within the failure JSON object.
You can add headers by clicking "Add", then you get a popup where you can set the name and value of the header.
Once created, they are added to the JSON Array response.headers within the failure JSON object, as a new object with the attributes name and value set to the entered name and value.
URL Rewrite allows you to rewrite URLs and change them.
URL Rewrite configuration is stored in a JSON object called urlrewrite within the location. This is an array of multiple JSON object, where each rule is its own object.
You can add, remove and reorder the rewrite rules.
When you press "Add" you get this screen where you can fill out the values.
When later editing the values, the screen looks like this:
Name of URL rewrite rule
Default: none
JSON key: name
Regular expression pattern
Default: none - must be specified
JSON key: pattern
Flags are one or more regular expression flags separated by comma, semicolon or pipe sign.
The flags can be UNIX_LINES, CASE_INSENSITIVE, COMMENTS, LITERAL, MULTILINE, DOTALL, UNICODE_CASE, CANON_EQ,UNICODE_CHARACTER_CLASS - see javadoc for java.util.regex.Pattern for details
Default: blank
JSON key: pattern.flags
New URL to rewrite to - URL can include $<n> where <n> is the number matching the reqular expression group in the pattern - e.g. /abc/(.*)/def/(.*) can be rewritten to /ABC123/$1/DEF123/$2 where $1 and 2 are replaced with the value in the appropriate group.
Default: none
JSON key: newurl
If set, URL will be decoded before matching - if not, URL will be encoded exactly as received from client.
Default: true
JSON key: decode.before.match
If set, all query parameters will be removed from the request, if rewriting the URL - if false, query parameters are kept.
Default: false
JSON key: clear.query.params
If set, redirect immediately (HTTP 302) to the new URL instead of continuing processing the next locations with the rewritten URL.
Default: false
JSON key: redirect
If pattern matches and URL is rewritten, no more rewrite rules for this location will be executed - remaining ones will be skipped
Default: false
JSON key: last
Like a location has conditions, the URL Rewrite rule also has conditions for when it will be triggered. You can add the same kind of conditions with the same rules as for locations.
These conditions are stored in the conditions JSON object within the specific URL Rewrite rule. See conditions above for explanation about each field.
IP Restriction allows you to specify under which conditions the client is allowed to change IP address.
IP Restriction information is stored in a JSON Object called ip.restriction within the location.
Set to allow clients to change IP addresses during a session - when not set, clients are not allowed to change IP address.
Default: false
JSON key: allowchange
Max. number of IP address changes allowed within a session - all the IP addresses the client has used during the session are stored within it for audit logging purposes.
Default: 32
JSON key: ip.address.maxcount
GeoIP Type: One of: [none, isp, organization, country, city, distance, complex] - none means no GeoIP checking done, complex means complex GeoIP rules are run, and ISP, organization, country, city means change is allowed with the same country, ISP etc... - distance allows change within a max. distance in kilometres.
Note that setting this to anything other than NONE requires that the GeoIP databases are loaded by the session controller – see geoip.database setting for the session controller for details. Also note that GeoIP data are not entirely accurate, depending on which level you look at. The Country and ISP data are fairly accurate, but organization, city and location accuracy is not as good. If the client switches IP address, the state variable “clientipaddresslist” will contain the list of IP addresses (other than the one embedded in the session ID) that the client has used previously. Note that this state variable is only updated if it is less than 2048 characters to ensure a client cannot flood the session size by changing IPs. Ceptor does not guarantee the accuracy of the GeoIP data. You can purchase more accurate databases directly from MaxMind. |
Default: none
JSON key: geoip.type
When GeoIP type is set to distance, this specifies max. kilometers allowed in distance.
Default: 100
JSON key: geoip.distance
List of complex GeoIP rules.
If type is set to COMPLEX, then these rules are enabled – here you can specify rules that allow very detailed control over which IP addresses it is possible for a user to switch between. The format is: keyword=keyword OR keyword=”string pattern” or distance=km – multiple conditions can be added separated by & These keywords exists: ip1, ip2, country1, country2, isp1, isp2, organization1, organization2, city1, city2,postal1, postal2, region1, region2, distance The ones ending with “1” represent the original IP address and the ones with “2” represent the new IP that the user is switching to. Let’s take a few simple rules…. country1=country2 Here, there is a match if both IP addresses are in the same country. isp1=isp2 Here, there is a match if both IP addresses are behind the same ISP. Now a little more complex… country1=country2&country1=”SE|DK|FI|NO” Here, switch is allowed within the same country, but ONLY if the country is Sweden, Denmark, Finland or Norway – users in other countries cannot switch IP. country1=country2&country1=”SE|DK|FI|NO”&distance=200 Same as before, but only within a distance of 200 kilometres. ip1=”2.104.*”&ip2=”2.104.*”&isp1=”Tele*|Telia” Here, switch is allowed for IP addresses 2.104.xxx.xxx but only if the original ISP matches the pattern “Tele*” or “Telia”. So, as you can see you can create some quite powerful and details rules to control exactly when switching is allowed. |
Default: none
JSON key: geoip.complexrules is an JSON Array containing a number of strings, where each string is a GeoIP Complex rule.
Script code runs to check if IP change is allowed.
See Plugins#IPcheckerscript for more information and samples.
Default: none
JSON key: script
IP change can also be restricted to specific ranges - you can specify multiple different ranges of IP addresses and allow switching from one address within a range to another in the same range.
IP Ranges are stored within the ip.restriction JSON object as ranges which is an array of JSON Objects, one for each range.
Here, you can add and remove ranges.When pressing "Add" you need to type in a name for a range.
When editing a range, you have these attributes:
Name of IP Range
Default: none
JSON key: name
List of values in range, prefix with {file} to read from a file.
Can be specified in the following formats
File containing ranges - e.g. {file}/filename.txt
Default: none
JSON key: values which are an array of strings - each string an entry in the list.
If the IP change was not allowed, this specifies what happens.
JSON Configuration is stored within a JSON object named action.invalid within the ip.restriction object.
Action to take for this location, if IP change was not valid. continue=go on without authenticating, respond=respond with configured response or redirect, and proxy=proxy onwards to destination (you rarely want this).
If action is set to RESPOND, then a response will be sent to the client with the information below.
Note that Scripts and Macros can be used to specify these values dynamically based upon request content.
Default: respond
JSON key:
Specify the name of a "canned" response here to reuse it - when set, the response sent back will be the one defined in the canned response - if any other values are specified here, HTTP response code, reason etc. then these values overwrite what was specified in the canned response. Any headers defined will complement the ones specified for the canned response.
Default: none
JSON key: response.name
HTTP Response code to send back to client.
Default: 500
JSON key: response.status
HTTP response reason text
Default: No additional information
JSON key: response.reason
Response Redirect Location URL - if set, a redirect will be sent instead of a normal response, the Location header in the response will be set to this value.
Default: none
JSON key: response.redirect
HTTP Response content-type
Default: none
JSON key: response.contenttype
Response body contents
Default: none
JSON key: response.body
Response headers can also be added to the response, if any are specified, they are in an JSON array called response.headers within the action.invalid JSON object.
You can add headers by clicking "Add", then you get a popup where you can set the name and value of the header.
Once created, they are added to the JSON Array response.headers within the action.invalid JSON object, as a new object with the attributes name and value set to the entered name and value.
Authentication configuration is described here: Location - Authentication
You can specify authorization checking for a location - which is used to check if the authenticated user has access to the location or not.
Configuration is stored within the JSON Object authorization within the location.
Check this if you do not want to attempt authorization for OPTIONS requests - this is required for CORS preflight requests to work in most browsers. Do take care to ensure you are not allowing access to anything you do not mean to, although the OPTIONS method in itself should be perfectly safe.
Default: false
JSON Key: noauthorization.for.options
List of roles/groups - if any roles are specified, at least one of them is required to access the resources.
Default: none
JSON key: roles which are an JSON Array of strings, each string is a role name.
Server identifier - used for additional role checking where an authorization plugin in the session controller might specify additional protected URLs that require other roles than those listed above. - set to "none" to disable.
An Authorization plugin in the session controller keeps track of protected URLs for different identifiers, so it might be configured with other protected resources than you have here - if the server id is not set to "none" then the authorization plugin is consulted too.
Default: default
JSON key: server.identifier
Specify a permission that you need to have to get access to this location. See Authorization for more information.
Permissions and ACLs can contain very advanced functionality, such as ABAC (Attribute Based Access Control) - see Authorization for more information. Note that some of these might result in a performance overhead. You can always check the Gateway Tracing to see the details about each request and diagnose any performance issues. |
Default: none
JSON key: permission.name
Name of scope that the user needs to successfully complete authorization.
Note that scope is only available when authenticating using OpenID Connect, API Key or bearer token related authentication methods - the scope is part of the OAuth2 / OpenID Connect protocols. |
Default: none
JSON key: scope.name
Name of IP Range to require for successful authorization - the callers remote IP must be in the configured range, or authorization will fail.
Default:none
JSON key: iprange
Script which can do custom authorization - the script must return true or false.
See Plugins - AuthorizationScript for an example.
Default: none
JSON key: authorization.script
If authorization fails, you can specify what response to send back to the client.
The configuration is stored in the JSON Object failure within the authorization object.
Action to take for this location, if authorization fails. continue=go on without authenticating, respond=respond with configured response or redirect, or proxy=forward request to a configured destination.
Default: respond
JSON key: action
Specify the name of a "canned" response here to reuse it - when set, the response sent back will be the one defined in the canned response - if any other values are specified here, HTTP response code, reason etc. then these values overwrite what was specified in the canned response. Any headers defined will complement the ones specified for the canned response.
Default: none
JSON key: response.name
HTTP Response code to send back to client.
Default: 500
JSON key: response.status
HTTP response reason text
Default: No additional information
JSON key: response.reason
Response Redirect Location URL - if set, a redirect will be sent instead of a normal response, the Location header in the response will be set to this value.
Default: none
JSON key: response.redirect
HTTP Response content-type
Default: none
JSON key: response.contenttype
Response body contents
Default: none
JSON key: response.body
Response headers can also be added to the response, if any are specified, they are in an JSON array called response.headers within the failure JSON object.
You can add headers by clicking "Add", then you get a popup where you can set the name and value of the header.
Once created, they are added to the JSON Array response.headers within the failure JSON object, as a new object with the attributes name and value set to the entered name and value.
Request Attributes can be set by specific locations, and used later by conditions in other locations, or by scripts. They can be useful for chaining locations, or extracting information once from e.g. a query / header parameter, and making it available for other locations/scripts.
If you click "Add" to add a new attribute, you can enter its name and value here:
Note that you can use Scripts and Macros to obtain the value.
Request attributes are stored in a JSON Array: request.attributes which contain an array of JSON Objects. Each object contains an attribute (name and value).
Name of request attribute.
Default: none, must be entered
JSON key: name
Value of the attribute - can be obtained using Scripts and Macros
Default: blank
JSON key: value
Here, you can modify the request headers that will later be sent to a target server when proxied to it.
Normally, you want to use this to add headers to the request, e.g. containing information about the user, attributes from the session, or the IP address / TCP Port of the client.
Configuration for request headers is stored in the JSON array request.headers within the location - each element in the array is a JSON Object containing a name and value.
If the value is an empty string, or null then the corresponding header will be removed from the request in case it was present already.
When you click Add, you get a dialog where you can enter a name and value:
You can edit the header name/value after adding it on this screen:
Name of HTTP Request header to add or replace
Default: none, must be specified
JSON key: name
Value of the HTTP Request header - set to an empty string or null to remove the header instead of adding it.
You can use Scripts and Macros to generate the value.
Default: blank
JSON key: value
Like with HTTP Headers, you can also add cookies to the request.
Configuration for request cookies is stored in an array of JSON Objects, called request.cookies - each element in the array contains the details for a single cookie.
Click "Add" to add a new cookie.
Here, you must enter only the name and value of the request cookie you wish to add.
Once entered, you can edit it where you get a chance to change all the available attributes for the cookie:
Please note that for request cookies, the only real relevant values here are name and value. The rest makes more sense for response cookies.
Name of cookie
Default: none
JSON key: name
HTTP Cookie value
Default: none
JSON key: value
HTTP Cookie path
Default: none
JSON key: path
HTTP Cookie domain
Default: none
JSON key: domain
Max-Age in seconds - beware of Internet Explorer which does not support this setting properly
Default: null
JSON key: maxage
Cookie is secure, meaning it will only be sent via encrypted https connections
Default: false
JSON key: secure
Cookie is marked as http only, meaning it will not be visible to javascript running in the browser
Default: false
JSON key: httponly
Instruct browser to discard cookie when browser terminates
Default: false
JSON key: discard
Cookie version
Default: null
JSON key: version
Date/time when cookie expires
Default: null
JSON key: expires
Cookie comment - rarely used
Default: null
JSON key: comment
You can configure HTTP Response Headers that are added to the response before sending it.
Response headers are stored in a JSON Array called response.headerswithin the location.
When you click "Add", you get the dialog below, where you can specify the name and value of the response header to add:
Once a header is added, you can edit it on this screen:
Name of HTTP Header
Default: none, must be specified
JSON key: name
Value of HTTP Header
You can use macros to change the value of a header from one thing to another - e.g. with this example: %{rewrite:responseheader:location;"http\:\/\/(.*)$";"CASE_INSENSITIVE";"https://$1"} Here, if the Location header starts with http:// then its value is changed to https:// and then the rest of the header. |
Default: empty
JSON key: value
Like with response headers, you can add cookies
Configuration for response cookies is stored in a JSON Array called response.cookies in the location object. Each element in the array is a JSON object with the individual cookie configuration.
When clicking "Add", you can enter the cookie name and value.
After adding a cookie, you can edit the details to provide the remaining information.
Name of cookie
Default: none
JSON key: name
HTTP Cookie value
Default: none
JSON key: value
HTTP Cookie path
Default: none
JSON key: path
HTTP Cookie domain
Default: none
JSON key: domain
Max-Age in seconds - beware of Internet Explorer which does not support this setting properly
Default: null
JSON key: maxage
Cookie is secure, meaning it will only be sent via encrypted https connections
Default: false
JSON key: secure
Cookie is marked as http only, meaning it will not be visible to javascript running in the browser
Default: false
JSON key: httponly
If set to lax or scrict, the cookie attribute SameSite=Strict or SameSite=Lax is added to the session cookies. This enables CSRF/XSRF attack protection - see https://tools.ietf.org/html/draft-west-first-party-cookies-07 for details.
Default: none
JSON key: samesite
Instruct browser to discard cookie when browser terminates
Default: false
JSON key: discard
Cookie version
Default: null
JSON key: version
Date/time when cookie expires
Default: null
JSON key: expires
Cookie comment - rarely used
Default: null
JSON key: comment
WebServer configuration is available if action is set to serve and is stored in the JSON object webserver within the location object.
If the location's action is set to serve then static resources are served for this location.
Path to the directory on the gateway machine where files are served from.
Default: none, must be specified
JSON key: path
If checked, file and directory names are considered case sensitive
Default: false
JSON key: case.sensitive
If checked, directory listing is allowed - note that this will reveal all files in the path and subdirectories to the caller
Default: false
JSON key: directory.listing.enabled
If checked, paths are canonicalized, meaning .. and . are resolved before attempting to read the file.
Default: true
JSON key: paths.canonicalize
If checked, symbolic links are resolved if they exist in the base path - note that "Safe paths" can be used to limit the safe paths that are valid for any eventual links.
Default: false
JSON key: follow.links
If "Follow symbolic links" is checked, this can limit the safe paths that files can be served from.
If left empty, all symlinks in the base path and in the paths the symlinks point to are allowed to serve files from.
Use semicolon or comma to separate pathnames.
Default: blank, meaning no limits defined if "Follow symbolic links" is checked.
JSON key: safe.paths
Size in bytes to use direct FS to network transfer (if supported by OS/JDK) instead of read/write.
For smaller files, the overhead of using the OS to transfer the files is larger, but for larger files the overall performance is better.
Default: 1024
JSON key: transfer.minsize
If checked, files are cached instead of loading them from disk on every access. If not checked none of the remaining options in this section are used.
Default: true
JSON key: cache.enabled
If checked, we attempt to ask the OS to listen for changes to files in the path and invalidate cache entries if a file is updated.
Note that on network drives this can lead to some overhead.
Default: false
JSON key: cache.changelistener
Maximum number of files to cache at one time.
Default: 1024
JSON key: cache.item.count
Maximum size in bytes of a file to place in the cache.
Default: 1048576 (1mb)
JSON key: cache.file.maxsize
"Time in seconds to cache a single file for - note that if "Monitor changes in base path" is checked and if the OS/JVM supports it then we will detect and invalidate the cache if a file has changed on disk
Default: 300
JSON key: cache.age.seconds
Memory limit for the disk cache - default is set to 10mb to conserve memory. Note that the cache is in native memory so java heap size is not affected
Default: 10485760 (10mb)
JSON key: cache.memory.bytes
This response will be sent if the browser requests a resource which was not found. If not defined, a simple html page containing only the words "Not found" in the body will be returned.
This section is stored in a JSON object response.notfound inside the webserver JSON object.
HTTP Response code to send back to client, should be 404
Default: 500
JSON key: response.status
HTTP response reason text
Default: No additional information
JSON key: response.reason
Response Redirect Location URL - if set, a redirect will be sent instead of a normal response, the Location header in the response will be set to this value.
Default: none
JSON key: response.redirect
HTTP Response content-type
Default: none
JSON key: response.contenttype
Response body contents
Default: none
JSON key: response.body
Nested locations are stored in the JSON object locations within the location object.
Nested locations can be added/removed and reordered just like regular locations.
A nested configuration is checked and processed only if the parent location conditions match and only when the action of the parent is set to CONTINUE - meaning only when the request has not already been proxied to somewhere else and when no response has been sent back to the client yet.