Page last updated:

Gorouter routes traffic coming into Cloud Foundry (CF) to the appropriate component, whether the request comes from an operator addressing the Cloud Controller or from an application user accessing an app running on a Diego Cell. Handling both platform and app requests with the same process centralizes routing logic and simplifies support for WebSocket and other types of traffic (for example, through HTTP CONNECT).

See the following instructions for help getting started with Gorouter in a standalone environment.


$ git clone https://github.com/cloudfoundry/gorouter.git
$ cd gorouter
$ git submodule update --init
$ ./bin/go install gorouter/gorouter
$ gem install nats


# Start NATS server in daemon mode
$ nats-server -d

# Start gorouter
$ ./bin/gorouter


Gorouter receives route updates through NATS. By default, routes that have not been updated in two minutes are pruned. Therefore, to maintain an active route, you must ensure that the route is updated at least every two minutes. The format of these route updates is as follows:

  "host": "",
  "port": 4567,
  "uris": [
  "tags": {
    "another_key": "another_value",
    "some_key": "some_value"

Such a message can be sent to both the gorouter.register subject to register URIs, and to the gorouter.unregister subject to deregister URIs, respectively.

$ nohup ruby -rsinatra -e 'get("/") { "Hello!" }' &
$ nats-pub 'gorouter.register' '{"host":"","port":4567,
Published [gorouter.register] : '{"host":"","port":4567,
$ curl my_first_url.vcap.me:8080


Gorouter provides /varz and /healthz http endpoints for monitoring.

The /routes endpoint returns the entire routing table as JSON. Each route has an associated array of host:port entries.

All of the endpoints require http basic authentication, credentials for which you can acquire through NATS. You can explicitly set the port, user and password (pass is the config attribute) in the gorouter.yml config file status section.

  port: 8080
  user: some_user
  pass: some_password

Example interaction with curl:

$ curl -vvv "http://someuser:somepass@"
* About to connect() to port 8080 (#0)
*   Trying
* Connected
* Connected to ( port 8080 (#0)
* Server auth using Basic with user 'someuser'
> GET /routes HTTP/1.1
> Authorization: Basic c29tZXVzZXI6c29tZXBhc3M=
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
> Host:
> Accept: */*
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Mon, 25 Mar 2013 20:31:27 GMT
< Transfer-Encoding: chunked


This section provides details about Gorouter logging.


The following table describes the log levels supported by Gorouter. The log level is specified in the configuration YAML file for Gorouter.

Message Description Examples
fatal Gorouter is unable to handle any requests due to a fatal error. Gorouter cannot bind to its TCP port, a CF component has published invalid data to Gorouter.
error An unexpected error has occurred. Gorouter failed to fetch token from UAA service.
info An expected event has occurred. Gorouter started or exited, Gorouter has begun to prune routes for stale droplets.
debug A lower-level event has occurred. Route registration, route unregistration.

Message Contents

This section section provides a sample Gorouter log entry and explanation of the contents.

[2017-02-01 22:54:08+0000] {"log_level":0,"timestamp":1485989648.0895808,"message":"endpoint-registered","source":"vcap.Gorouter.registry","data":{"uri":"0-*.login.bosh-lite.com","backend":"","modification_tag":{"guid":"","index":0}}}

Property Description
log_level Logging level of the message
timestamp Epoch time of the log
message Content of the log entry
source Gorouter function that initiated the log entry
data Additional information that varies based on the message

About Access Logs

This section provides details about Gorouter access logs.

Gorouter generates an access log in the following format when it receives a request:

<Request Host> - [<Start Date>] "<Request Method> <Request URL> <Request Protocol>" <Status Code> <Bytes Received> <Bytes Sent> "<Referrer>" "<User-Agent>" <Remote Address> <Backend Address> x_forwarded_for:"<X-Forwarded-For>" x_forwarded_proto:"<X-Forwarded-Proto>" vcap_request_id:<X-Vcap-Request-ID> response_time:<Response Time> gorouter_time:<Gorouter Time> app_id:<Application ID> app_index:<Application Index> x_cf_routererror:<X-Cf-RouterError> <Extra Headers>

Gorouter access logs are also redirected to syslog.

See the list below for more information about the Gorouter access log fields:

  • The following are optional fields: Status Code, Response Time, Application ID, Application Index, X-Cf-RouterError, and Extra Headers.

  • If the access log lacks a Status Code, Response Time, Application ID, Application Index, or X-Cf-RouterError, the corresponding field shows -.

  • Response Time is the total time it takes for the request to go through the Gorouter to the app and for the response to travel back through the Gorouter. This includes the time that the request spends traversing the network to the app and back again to the Gorouter. It also includes the time the app spends forming a response.

  • Gorouter Time is the total time it takes for the request to go through the Gorouter initially plus the time it takes for the response to travel back through the Gorouter. This does not include the time the request spends traversing the network to the app. This also does not include the time the app spends forming a response.

  • X-Cf-RouterError is populated if the Gorouter encounters an error. The returned values can help distinguish whether a non-2xx response code is due to an error in the Gorouter or the backend. For more information on the possible errors, see the Router Errors section.

Router Errors

The following table lists possible values of the X-Cf-RouterError header:

Value Description
invalid_cf_app_instance_header The provided value for the X-Cf-App-Instance header does not match the required format of APP_GUID:INSTANCE_ID.
empty_host The value for the Host header is empty, or the Host header is equivalent to the remote address. Some load balancers optimistically set the Host header value to their IP address when there is no value present.
unknown_route The desired route does not exist in the Gorouter’s route table.
no_endpoints There is an entry in the route table for the desired route, but there are no healthy endpoints available.
Connection Limit Reached The backends associated with the route have reached their maximum number of connections. The maximum number of connection for backends is set via the property router.backends.max_conns in the Gorouter spec.
route_service_unsupported Route services are not enabled. You can enable route services with the property router.route_services_secret in the Gorouter spec. If the property is empty, route services are disabled.
endpoint_failure The registered endpoint for the desired route failed to handle the request.
Create a pull request or raise an issue on the source for this page in GitHub