Huxley proxy logo

Huxley 2 Community Edition

A cross-platform JSON proxy for the GB railway Live Departure Boards SOAP API


Huxley 2 is a CORS enabled cross-platform JSON ReST proxy for the GB NRE LDB WCF SOAP XML API (called Darwin). It supports both the Public Version (PV) and the Staff Version (SV). It's built with ASP.NET Core LTS (.NET 6.0), C# 10 and lots of abbreviations!

The primary purpose of Huxley 2 is to allow easy use of the LDB API from browser-based client-side PWAs made with JavaScript or TypeScript. Additionally, it opens up the Windows enterprise API to agile developers on macOS and Linux.

Get Started

Version 2.0.5

Contents

Version 2 Changes

There are some significant changes from version 1:

  • Reimplementation on ASP.NET Core allowing Huxley to run on Windows, macOS and Linux
    • You can now use Huxley on any platform (pun intended)
    • .NET 6.0 LTS supported until 2024-11-08
  • Support for time offset and window parameters allowing queries for past trains
  • Station code retrieval from staff reference web service (if staff token is in settings)
  • Optional update check
  • Response caching support (wasn't available on old WebAPI controllers)
  • Improved performance and flexible architecture using agile best practices
  • Modern and simplified code base using the latest C# language features
    • C# 10, nullable and non-nullable reference types used throughout
    • A full suite of automated unit tests and CI/CD pipelines
  • ETag support

Quick Start

Follow these steps to get going:

  • Get an API access token from NRE (public or staff or both)
  • Append accessToken=TOKEN to the URL for every request

If you don't want to append the token then read on.

Access Tokens

You will need to add your access token to the configuration file or URL. You can register to obtain one here (or here for the staff version).

Append accessToken={Your GUID token} to the URL for every request. If using the staff versions then you will need to use your staff token.

There is optional support for configuring the access token server-side. So you don't need to worry about revealing it in URLs or source code.

In the appsettings.json file you can set tokens and other settings. You can set DarwinAccessToken to your NRE access token. If you leave ClientAccessToken as an empty string then no token is required in the Huxley URL. If you set ClientAccessToken to a string and it matches the token in the URL then the DarwinAccessToken will be used instead in the SOAP call. Otherwise the URL token is passed straight through.

You can do the same with DarwinStaffAccessToken if you are using the staff version of the API. Both share a ClientAccessToken so your client only needs one token (or none).

N.B. You should set up these tokens in your deployment platform and not in your source code repository. You'll notice that the values are blank by default.

API Endpoints

Most of these endpoints (except delays and crs) map directly to the SOAP API. Refer to the official documentation pages for the public and staff web services for more details, but be aware that these are not entirely accurate.

Station Boards

There are five station boards and their staff equivalents, plus a delays board that Huxley provides.

URL Format

The URL format is {board}/{CRS|StationName}/{filterType}/{filterCRS|StationName}/{numRows} or {board}/{CRS|StationName}/{numRows} (arrivals/departures only) where only board and CRS (or a station name) are required. The filter type can be either to or from (case is not important).

A station name can be used in place of CRS codes if the name matches only one station (or matches one exactly) but case is not important. See the CRS section below for more information.

For all boards (except delays) you can add an expand=true parameter to embed all service details into the board response. The delays board is expanded by default.

/all/{CRS|StationName}?expand=true

You can optionally add timeOffset (-120 to 119 inclusive) and timeWindow (-120 to 120 inclusive) parameters in minutes. For example, to get services for the next hour and last fifteen minutes: /all/{CRS|StationName}?timeOffset=-15&timeWindow=75

Examples:

Departures

/departures/{CRS|StationName}

Arrivals

/arrivals/{CRS|StationName}

Departures and Arrivals

/all/{CRS|StationName}

Next

/next/{CRS|StationName}/{filterType}/{filterCRSs|StationNames}

Filter stations can be a comma separated list. Filter type and number of rows are ignored.

Fastest

/fastest/{CRS|StationName}/{filterType}/{filterCRSs|StationNames}

Filter stations can be a comma separated list. Filter type and number of rows are ignored.

Staff Departures

/staffdepartures/{CRS|StationName}

Staff Arrivals

/staffarrivals/{CRS|StationName}

Staff Departures and Arrivals

/staffall/{CRS|StationName}

Staff Next

/staffnext/{CRS|StationName}/{filterType}/{filterCRSs|StationNames}

Staff Fastest

/stafffastest/{CRS|StationName}/{filterType}/{filterCRSs|StationNames}

Delays

The delays action performs calculations server side to easily let you know if there are problems on a particular route. Filter is required.

/delays/{CRS|StationName}/{filterType}/{filterCRS|StationName}/{numRows}

Additionally, this action will accept LON or London as a filter CRS to find trains going to or coming from any of the London Terminals.

You can also pass in a comma separated list of 24 hour train times to filter on (e.g. /delays/btn/to/lon/10/0729,0744,0748).

Sample Response
{
  "generatedAt": "2024-12-13T17:32:58.8989963+00:00",
  "locationName": "Clapham Junction",
  "crs": "CLJ",
  "filterLocationName": "London",
  "filtercrs": "LON",
  "filterType": 1,
  "delays": true,
  "totalTrainsDelayed": 1,
  "totalDelayMinutes": 0,
  "totalTrains": 6,
  "delayedTrains": [
    {
      "origin": [
        {
          "locationName": "London Victoria",
          "crs": "VIC",
          "via": null,
          "futureChangeTo": null,
          "assocIsCancelled": false
        }
      ],
      "destination": [
        {
          "locationName": "Littlehampton",
          "crs": "LIT",
          "via": "via Hove & Worthing",
          "futureChangeTo": null,
          "assocIsCancelled": false
        }
      ],
      "currentOrigins": null,
      "currentDestinations": null,
      "rsid": "SN382200",
      "serviceIdPercentEncoded": "Aum4%2FnXk%2B02wKUVqlS7JAQ%3D%3D",
      "serviceIdGuid": "feb8e902-e475-4dfb-b029-456a952ec901",
      "serviceIdUrlSafe": "Aum4_nXk-02wKUVqlS7JAQ",
      "sta": "17:32",
      "eta": "Delayed",
      "std": "17:32",
      "etd": "Delayed",
      "platform": "13",
      "operator": "Southern",
      "operatorCode": "SN",
      "isCircularRoute": false,
      "isCancelled": false,
      "filterLocationCancelled": false,
      "serviceType": 0,
      "length": 8,
      "detachFront": false,
      "isReverseFormation": false,
      "cancelReason": null,
      "delayReason": "This train has been delayed by a fault on this train",
      "serviceID": "Aum4/nXk+02wKUVqlS7JAQ==",
      "adhocAlerts": null
    }
  ]
}

CRS Station Codes

CRS station codes are available from the following endpoint:

/crs/{query}

If query is omitted then all CRS codes are returned along with their respective station names.
If query is provided then only station names matching it will be returned along with their CRS codes.

Example response for/crs/oswald
[
  {
    "stationName": "Church & Oswaldtwistle",
    "crsCode": "CTW"
  },
  {
    "stationName": "Lazonby & Kirkoswald",
    "crsCode": "LZB"
  }
]

/crs/london terminals returns all codes in the London station group

Service

/service/{Service ID}

The service ID can be found for each service inside the departures and arrivals response. Huxley also returns the ID in URL percent encoded, GUID and URL safe Base64 representations (for non-staff boards). Likewise, the service endpoint will accept URL safe Base64 service IDs, from various different encoders.

This endpoint also accepts the GUID representation of the ID

If the ID is a RID (a 15 digit long integer) then the staff API will be used. In this case a staff access token must be used (unless configured server side).

Source Code

Source code is available on GitHub.

This project is treeware! If you found it useful then please plant a tree for me.

Buy me a tree!

License

Licensed under the EUPL-1.2-or-later.

The EUPL covers distribution through a network or SaaS (like a compatible and interoperable AGPL).


© 2024 James Singleton

powered by National Rail Enquiries