Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The Ceptor Gateway supports a number of ways of extending it, either using custom Java code or scripts (e.g. javascript code).

...

Code Block
package io.ceptor.gateway.state;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.jboss.logging.MDC;

import dk.itp.security.passticket.IAgent;
import dk.itp.security.utils.UniqueId;
import dk.portalprotect.geolocator.LocatorInfo;
import io.ceptor.config.gateway.Config;
import io.ceptor.config.gateway.Config.CookieSnapper;
import io.ceptor.config.gateway.Config.Location;
import io.ceptor.gateway.Gateway;
import io.undertow.client.ClientExchange;
import io.undertow.client.ClientRequest;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.handlers.form.FormData;
import io.undertow.util.Headers;

public class StateHolder {
	public ConcurrentHashMap<String, ?> state = new ConcurrentHashMap<>();
	
	public UniqueId sessionId;
	/** Will contain the request/session ID once processing is started - can be used by scripts */
	public String id;
	
	public Config config;
	public IAgent agent;
	/** HttpExchange for the original request - will be null for ping requests */
	public HttpServerExchange httpExchange;
	/** Will only be present for ping requests - null for all normal requests */
	public ClientRequest pingRequest;
	
	public Gateway gateway;
	
	/** If any exception occurred during processing, e.g. authentication failure - it is available here for scripts to use */
	public Throwable exception;
	
	public List<Location.Headers> pendingRequestHeaders = new ArrayList<>();
	public List<Location.Cookies> pendingRequestCookies = new ArrayList<>();
	
	public List<Location.Headers> pendingResponseHeaders = new ArrayList<>();
	public List<Location.Cookies> pendingResponseCookies = new ArrayList<>();
	public HashMap<String, String> requestAttributes = new HashMap<>();
	public HashMap<String, CompletedRequest> completedRequests = new HashMap<>();
	
	public List<CookieSnapper> cookieSnappers = new ArrayList<>();
	
	/** The original Path before being rewritten, if any */
	public volatile String originalPath;
	/** The original URI before being rewritten, if any */
	public volatile String originalURI;
	/** The original scheme before being rewritten, if any */
	public volatile String originalScheme;
	/** The original host header before it was rewritten, if any */
	public volatile String originalHost;
	/** Original non-rewritten URL as it was before rewriting it */
	public volatile String originalUrlBeforeRewrite;
	
	/** Time that this request started to be proxied */
	public volatile long proxyStartTimestamp;
	
	public LocatorInfo geoip;
	
	public Tracer trace;
	
	public volatile Config.Destination currentDestination;	
	public volatile Config.Location currentLocation;

	/** The exception that was set as input to setAndLogError - this might go in the accesslog */
	public volatile Throwable error;
	
	/** When request content has already been read, we can find it here - this is done if some plugin or location needs access to it, e.g. POST data. */
	public volatile byte[] prefetchedRequestContent;
	/** If request content contained form input data, it is here */
	public volatile FormData formData;
	
	/** Determines if session was authenticated when the request arrived */
	public volatile boolean wasAuthenticatedAtRequestTime;
	/** True, if the session originated from a cookie */
	public volatile boolean sessionOriginatedFromCookie;
	/** True, if session fixation cookie was already added */
	public volatile boolean fixationCookieAdded;
	
	/** API Manager related information - if available for client */
	public volatile io.ceptor.apimanager.Config.APIPartner apiPartner;
	public volatile io.ceptor.apimanager.Config.APIPartnerApplication apiPartnerApplication;
	
	/** The ID of the API that the API Gateway served, or null if none was used */
	public volatile String apiId;
	/** The API descriptor, if an API was processed - useful for extracting extra data for logging */
	public MethodAndPathToAPIVersion apiDescriptor;

	/** These variables are added to the SLF4J MDC, and are then available for use in logging definitions */
	public Map<String,String> logContextVariables = new HashMap<>();

	
	/** Any response hooks picked up while processing locations are stored here and called when a response is received as a result of proxying a call */
	public List<Config.ResponseHook> responseHooks = new ArrayList<>();
	
	/** 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;

	/**
	 * Returns the query or POST parameter - if the request contains a body with query parameters, they will be searched first, then the POST parameters.
	 * 
	 * @param name Name of query parameter
	 * @return Value, or null if not found.
	 */
	public String getQueryOrPostParam(String name);
	
	/**
	 * Returns a Deque<String> list of the query of POST parameter values - if the request contains a body with query parameters, they will be searched first, then the POST parameters.
	 * 
	 * @param name Name of query parameter
	 * @return List of values, or null if not found.
	 */
	public Deque<String> getQueryOrPostParams(String name);

	/**
	 * Returns the path template parameter within the path, if found.
	 * @param pathTemplate Template - e.g. /mypath/{username}/other/{shoesize}
	 * @param parameterName Name of parameter, e.g. username to look for in the path
	 * 
	 * @return Parameter value, or null if not found
	 */
	public String getPathTemplateParam(String pathTemplate, String parameterName);

	public String getSessionVariable(String name) throws PTException {
		return agent.getStateVariable(id, name);
	}
	
	public boolean isResponseStartedOrSent() {
		return isResponseSent || httpExchange.isResponseStarted();
	}
	
	public String macro(String macro) throws ScriptException, ParseException, IOException {
		Mapper<StateHolder> mapper = Mapper.parse(macro, new StateHolderReplacerFactory());
		return mapper.map(callback, this);
	}


	public void respond(int responseCode, String reason, String contentType, String body) {
		gateway.sendResponse(this, responseCode, reason, contentType, body);
	}
	
	public void respond(int responseCode, String reason, String contentType, byte[] body) {
		gateway.sendResponse(this, responseCode, reason, contentType, body);
	}
	
	public void respond(int responseCode, String reason, String contentType, ByteBuffer body) {
		gateway.sendResponse(this, responseCode, reason, contentType, body);
	}


	/**
	 * Add a new entry to the SLF4J MDC (Multiple Diagnostics Context) - this is then available for logging
	 * 
	 * @param key Key to add
	 * @param value The value
	 */
	public void addToMDC(String key, String value);
}

// CompletedRequest contains the result of a service call task within a pipeline
public final class CompletedRequest {
	public volatile long startedAt = System.currentTimeMillis();
	public volatile long endedAt;
	public volatile int tries;
	public volatile boolean isCancelled;
	public volatile Exception exception;
	public volatile byte[] response;
	public volatile int responseCode;
	public volatile String responseReason;
	public volatile HeaderMap responseHeaders;

    /* Returns the response converted to a string in the character set indicated by the content-type response header */
	public String getResponseAsString();
}

...

Code Block
if (input.indexOf('Looks good to me') != -1)
  true;
else
  false;


IP Checker Script

Script must return true or false to indicate if it is ok to swith to the new IP address.

The variable input contains the new IP address the client is switching to. The variable state contains all information about the request.

...

Code Block
if (input == '127.0.0.1') true; else false;

Another example - here checking the original IP:

Code Block
if (input == '127.0.0.1' || context.gateway.getClientSourceIP(state) == '10.0.0.1') true;

...