Config - Locations

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

Locations are stored as separate JSON objects in the locationsarray in the gateway JSON configuration.

Example locations:

{
  "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": []
}


Locations configuration

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.

Configuration for Each Specific Location

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.

Location configuration

Name

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 

Location is enabled

If unchecked, This location is ignored and not processed - it is treated like it did not exist.

Default: true
JSON key: location.enabled

Session is needed

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

Session will only be established if conditions match

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

Override global session settings

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

Preload request content

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

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

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 

Proxy Destination

Destination to forward request to, if action is proxy.

Default: blank
JSON key: proxy.destination 

Compress proxied responses

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 

Limits

Can be used to limit the number of concurrent requests, or requests per second for this location.

Limit Qualifier

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

Max requests per second

Maximum number of requests per second, set to 0 for no limit.

Default: 0 (no limit)
JSON key: request.persecond.max 

Maximum concurrent requests

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 

Request queue size

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 

Max response bytes/s

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 

Location Script

Script

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

Pipeline Settings

See Pipelines and Tasks for more information about pipelines.

Pipeline

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.

Response settings (when action is "respond")

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.

Canned Response

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

HTTP Response code to send back to client.

Default: 500
JSON key: response.status 

HTTP Response reason

HTTP response reason text

Default: No additional information
JSON key: response.reason 

Redirect Location

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

Content-Type

HTTP Response content-type

Default: none
JSON key: response.contenttype

Response Body

Response body contents

Default: none
JSON key: response.body 

CookieSnapper

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.

Cookies to snap

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

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

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.

Request wrapper java class

Java class implementing ConduitWrapper<StreamSourceConduit> to process request body - see Plugins#JavaRequestWrapper for more information.

Default: none
JSON key: request.wrapper.class 

Response wrapper java class

Java class implementing ConduitWrapper<StreamSinkConduit> to process response body - see Plugins#JavaResponseWrapper for more information.

Default: none
JSON key: response.wrapper.class 

Request wrapper script

Script that processes request body - see Plugins#ScriptRequestWrapper for more information.

Default: none
JSON key: response.wrapper.script

Response wrapper script

Script that processes response body see Plugins#ScriptResponseWrapper for more information.

Default: none
JSON key: response.wrapper.script

Session

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.

Invalid Session Action

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 if request contained invalid or timed out session ID

Action

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.

Canned Response

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

HTTP Response code to send back to client.

Default: 500
JSON key: response.status 

HTTP Response reason

HTTP response reason text

Default: No additional information
JSON key: response.reason 

Redirect Location

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

Content-Type

HTTP Response content-type

Default: none
JSON key: response.contenttype

Response Body

Response body contents

Default: none
JSON key: response.body 

Response Headers

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.

Conditions

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.

Condition match

Type

Type of condition.

You can select between these types:

  • path
    Request URI / Path - e.g. /*, /secret/* or *.png 
  • host
    Hostname  of the request, e.g. app.*, *.my.domain or login.ceptor.io
  • cookie
    Request cookie value (name must contain the name of cookie).
  • query
    Request query parameter - /?param=value (name must be query parameter name).
  • postparam
    A request POST parameter sent in a URL form-encoded POST request.  (name must be post parameter name).
  • pathparam
    A request path parameter - similar to query parameters, but separated with semicolon instead of question mark - e.g. /somepath;param=value;param2=value2 (name must be path parameter name).
  • method
    Request HTTP method, e.g. GET, HEAD, POST, PUT etc. 
  • scheme
    Request scheme - either http or https.
  • header
    The value of a specific HTTP request header, e.g. the Accept header (name must be HTTP request header name).
  • remoteip
    The remote IP address the request originated from.
  • attribute
    A request attribute - not part of the request, but can be the result of an earlier location - request attributes can be created by a location and reused in conditions for later locations. (name must contain the name of the attribute).
  • geoip
    A specific Geo IP attribute, such as a country, ISP or city. (name must be set to isp, organization, countrycode, countryname, city, postalcode or region).
  • userid
    A specific user ID (note that for this information to be available, the location needs to have the "Session is needed" flag set).
  • usergroup
    A specific user group (note that for this information to be available, the location needs to have the "Session is needed" flag set).
  • script
    This allows you to create a script which can use any means to decide what conditions are required to match, it could, for example, check a time interval or do complex validation of multiple session attributes and request content.
  • macro
    Allows you to check the value of a macro, e.g. check if %{SERVER_ADDR} matches a specific IP address.
  • probability
    Specify a percentage probability of match - this enables a condition that matches a percentage of the requests, e.g. 10% - use this to send e.g. 10 or 20% of requests to a different version than the rest to allow gradual upgrades that do not affect all users.

Default: none - must be selected.
JSON key: type 

Name

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 

Values must NOT match

Reverse the check, so if one of the values match, the condition is NOT met.

Default: false
JSON key: deny 

Lowercase before checking against value

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

Values

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. 

Response Hooks

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.

Response Hook configuration

HTTP Response Status code

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

Script

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:

context.gateway.sendResponse(context, context.currentResponseHook.response);


Default: none
JSON key: script

Response settings

Send this response instead of proxied response

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

Canned Response

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

HTTP Response code to send back to client.

Default: 400
JSON key: response.status 

HTTP Response reason

HTTP response reason text

Default: No additional information
JSON key: response.reason 

Redirect Location

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

Content-Type

HTTP Response content-type

Default: none
JSON key: response.contenttype

Response Body

Response body contents

Default: none
JSON key: response.body 

Response Headers

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.

URL Validation

URL Validation

Configuration for URL validation is stored in the JSON objecurl.validator 

Enable URL validation

Enable or disable this URL validator

Default: false
JSON key: enabled 

Verify URL Encoding

If set, verifies that URL Encoding is valid.

Default: true
JSON key: verify.encoding 

Query param name max length

Max length of query parameter name, or 0 to disable validation.

Default: 1024
JSON key:  query.key.maxlength

Query param value max length

Max length of query parameter value, or 0 to disable validation.

Default: 8192
JSON key:  query.value.maxlength

URL max length

Max length of entire URL, or 0 to disable validation.

Default: 32768
JSON key:  maxlength

Additional validation

Verify Full URL

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

Authority Regex validation pattern

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

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

{regex}^[a-zA-Z0-9_]*$

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.

Parameter Validation

Require specified parameters

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

Allow additional parameters

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

Verify query parameters

If checked, query parameters are validated, otherwise they are ignored.

Default: true
JSON Key: verify.queryparams

Verify POST parameters

If checked, POSTbparameters are validated, otherwise they are ignored.

Default: true
JSON Key: verify.postparams

Verify path parameters

If checked, path parameters are validated, otherwise they are ignored.

Default: true
JSON Key: verify.pathparams

Parameters

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:

  • Name Pattern
    Specify a pattern or prefix with {regex} to specify a regular expression - used to specify the key/name of parameters to match.
  • Value Pattern
    Specify a pattern or prefix with {regex} to specify a regular expression - used to specify the valid value of parameters matching the name pattern.
  • Lowercase name before comparing
    Check to lowercase parameter name before comparing with the pattern.
  • Lowercase value before comparing
    Check to lowercase parameter value before comparing with pattern.

JSON Key: verify.params - Contains an array of JSON Objects, each parameter object has these values;

  • key - Key pattern - can optionally be prefixed by {regex} to specify a regular expression instead of a pattern with wildcards.
  • value - Value pattern, can also be prefixed with {regex} to specify a regular expression.
  • key.lowercase - If true, the key will be lowercased before comparing to the key pattern, essentially making the comparison case insensitive as long as the key is specified in lowercase in this parameter.
  • value.lowercase - If true, the value will be lowercased before comparing to the pattern to check for a match.

Failure Action


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

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 

Canned Response

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

HTTP Response code to send back to client.

Default: 400
JSON key: response.status 

HTTP Response reason

HTTP response reason text

Default: No additional information
JSON key: response.reason 

Redirect Location

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

Content-Type

HTTP Response content-type

Default: none
JSON key: response.contenttype

Response Body

Response body contents

Default: none
JSON key: response.body 

Response Headers

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

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:

URL Rewrite configuration

Name

Name of URL rewrite rule

Default: none
JSON key: name 

Regex pattern

Regular expression pattern

Default: none - must be specified
JSON key: pattern 

Regex flags

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

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 

Decode URL before matching

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 

Remove all query params from request

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 

Redirect

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 

Last rule

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 

Conditions

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

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.

IP Change Restriction configuration

Allow client to change IP address

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 IPs in session

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

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 

GeoIP Distance

When GeoIP type is set to distance, this specifies max. kilometers allowed in distance.

Default: 100
JSON key: geoip.distance 

GeoIP Complex Rules

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.
If a single rule in the list matches, access is allowed and no further checking is done against the other rules in the list. The log ins contains detailed information when IP switching was allowed, including the name of the rule that allowed access.
After changing these rules (especially the more complex ones), it is a good idea to monitor the logs to verify that they work as intended.

Default: none
JSON key: geoip.complexrules is an JSON Array containing a number of strings, where each string is a GeoIP Complex rule. 

IP Checking script

Script code runs to check if IP change is allowed.
See Plugins#IPcheckerscript for more information and samples.

Default: none
JSON key: script

IP Ranges

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:

IP Range

Name

Name of IP Range

Default: none
JSON key: name 

IPs

List of values in range, prefix with {file} to read from a file.

Can be specified in the following formats

  • Single IP Address - e.g. 127.0.0.1
  • IP Range - e.g. 192.168.1.1-192.168.1.16
  • CIDR bits notation - e.g. 192.168.1.0/30
  • CIDR netmask notation - e.g. 192.168.1.0/255.255.255.0
  • 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. 

Failure Action

If the IP change was not allowed, this specifies what happens.

Action when IP is not valid

JSON Configuration is stored within a JSON object named action.invalid within the ip.restriction object.

Action

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:  

Canned Response

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

HTTP Response code to send back to client.

Default: 500
JSON key: response.status 

HTTP Response reason

HTTP response reason text

Default: No additional information
JSON key: response.reason 

Redirect Location

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

Content-Type

HTTP Response content-type

Default: none
JSON key: response.contenttype

Response Body

Response body contents

Default: none
JSON key: response.body 

Response Headers

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

Authentication configuration is described here: Location - Authentication

Authorization

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.

Authorization

OPTIONS method bypasses authorization

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

Required roles

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

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 

Permission Name

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

Scope 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

IP Range

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

Authorization script

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 

Authorization Failure

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 when authorization fails

Action

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 

Canned Response

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

HTTP Response code to send back to client.

Default: 500
JSON key: response.status 

HTTP Response reason

HTTP response reason text

Default: No additional information
JSON key: response.reason 

Redirect Location

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

Content-Type

HTTP Response content-type

Default: none
JSON key: response.contenttype

Response Body

Response body contents

Default: none
JSON key: response.body 

Response Headers

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

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).

Attribute configuration

Name

Name of request attribute.

Default: none, must be entered
JSON key: name 

Value

Value of the attribute - can be obtained using Scripts and Macros

Default: blank
JSON key: value 

Request Headers

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:
 

HTTP Header configuration

Name

Name of HTTP Request header to add or replace

Default: none, must be specified
JSON key: name 

Value

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

Request Cookies

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:

Cookie configuration

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

Name of cookie

Default: none
JSON key: name 

Value

HTTP Cookie value

Default: none
JSON key: value 

Path

HTTP Cookie path

Default: none
JSON key: path 

Domain

HTTP Cookie domain

Default: none
JSON key: domain 

Max Age (seconds)

Max-Age in seconds - beware of Internet Explorer which does not support this setting properly

Default: null
JSON key: maxage 

Secure

Cookie is secure, meaning it will only be sent via encrypted https connections

Default: false
JSON key: secure 

Http only

Cookie is marked as http only, meaning it will not be visible to javascript running in the browser

Default: false
JSON key: httponly 

Discard

Instruct browser to discard cookie when browser terminates

Default: false
JSON key: discard

Version

Cookie version

Default: null
JSON key: version 

Expires

Date/time when cookie expires

Default: null
JSON key: expires 

Comment

Cookie comment - rarely used

Default: null
JSON key: comment 

Response Headers

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:
 

HTTP header configuration

Name

Name of HTTP Header

Default: none, must be specified
JSON key: name 

Value

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 

Response Cookies

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.

Cookie configuration

Name

Name of cookie

Default: none
JSON key: name 

Value

HTTP Cookie value

Default: none
JSON key: value 

Path

HTTP Cookie path

Default: none
JSON key: path 

Domain

HTTP Cookie domain

Default: none
JSON key: domain 

Max Age (seconds)

Max-Age in seconds - beware of Internet Explorer which does not support this setting properly

Default: null
JSON key: maxage 

Secure

Cookie is secure, meaning it will only be sent via encrypted https connections

Default: false
JSON key: secure 

Http only

Cookie is marked as http only, meaning it will not be visible to javascript running in the browser

Default: false
JSON key: httponly 

SameSite

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

Discard

Instruct browser to discard cookie when browser terminates

Default: false
JSON key: discard

Version

Cookie version

Default: null
JSON key: version 

Expires

Date/time when cookie expires

Default: null
JSON key: expires 

Comment

Cookie comment - rarely used

Default: null
JSON key: comment 

WebServer

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.

WebServer - Serve static resources

Path

Path to the directory on the gateway machine where files are served from.

Default: none, must be specified
JSON key: path

Case sensitive filenames

If checked, file and directory names are considered case sensitive

Default: false
JSON key: case.sensitive

Directory listing enabled

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

Canonicalize paths

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

Safe paths

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

Minimum filesize to enable OS transfer

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

Cache settings

Enable caching of files

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

Monitor changes in base path

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

File count

Maximum number of files to cache at one time.

Default: 1024
JSON key: cache.item.count

File max size

Maximum size in bytes of a file to place in the cache.

Default: 1048576 (1mb)
JSON key: cache.file.maxsize

Age in seconds

"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

Cache memory limit

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

404 Not Found Response

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

HTTP Response code to send back to client, should be 404

Default: 500
JSON key: response.status 

HTTP Response reason

HTTP response reason text

Default: No additional information
JSON key: response.reason 

Redirect Location

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

Content-Type

HTTP Response content-type

Default: none
JSON key: response.contenttype

Response Body

Response body contents

Default: none
JSON key: response.body 

Nested Locations

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.


© Ceptor ApS. All Rights Reserved.