Skip to main content

URL Connections

A connection configuration specifies how the rendering service will handle outgoing HTTP requests on behalf of the project. This encompasses all situations when the cloud service acts as an HTTP client calling external servers to achieve its tasks. There are four main cases form this:

  • /config.ion
    • rendering service must read image files from remote systems to integrate them into the PDF, e.g., from a MAM system or from the image folder of the public web shop of a company.
  • /upload/config.ion
    • rendering service must upload the generated PDF to a remote server (http or ftp)
  • /callback/config.ion
    • rendering service must notify the originating server about the success of a rendering
    • this will include the URL where the PDF can be downloaded
  • /error/config.ion
    • rendering service must notify the originating server about the failure of a rendering
    • this will include a detailed error message

All these cases have in common that the service will use only URLs that are explicitly configured. If a request does not match any defined base URI in the configuration ion file, it will not be executed.

General Structure

  • Config files supporting URL connection configuration contain a root property called connections.
  • The "connections" property is an (optionally empty) array of Connection objects.
  • A connection object is identified by its URI, which is matched against real URIs as used by mediaproxy or webhook workers. The best matching connection configuration for a real uri is defined as the connection with the longest matching path from the start of the URI.
  • If a connection matches for a real URI, the request headers, authorization and other settings from the configuration are applied to that URI call.

Typical example from "/config.ion" for mediaproxy

{
"connections": [
{
"url": "https://example.com/protected/images",
"authentication": {
"type": "Bearer",
"value": "eyJmb28iOiJiYXIifQ=="
},
"cache": {
"max-duration": 600,
// 1 h
"ignore-cache-control": true
}
}
]
}

This defines one connection configuration.

Read this as follows:

  • If a request is made to a URL starting with https://example.com/protected/images then
    • add the content type "application/x-test" to the request
    • and use bearer token authentication, i.e., in this case add a header "Authorization: Bearer eyJmb28iOiJiYXIifQ=="
    • cache the results for a maximum of 10 minutes
    • ignore the Cache-Control headers as sent from the server (e.g., because that server wrongly sends "Expires: now" always).

This is typical for mediaproxy configuration where only GET requests are used.

Complex Example from "callback/config.ion"

{
"connections": [
{
"method": "POST",
"url": "https://example.com/priint-cloud-connector/v1/callback",
"header": {
"x-useragent": "mypriintcloudproject",
"content-type": "application/json"
},
"authentication": {
"type": "OAuth2",
"grantType": "Password",
"clientId": "ce129d64e40d47fa48ddad7c70b1dcd9",
"clientSecret": "Y2UxMjlkNjRlNDBkNDdmYTQ4ZGMjlkNjRlNDBkRhZDdjNzBiMWRjZDk",
"username": "priintcloud-worker",
"password": "S*meS*cr*tCh*rs",
"scope": "readwrite"
},
"payload": [
{
"value": "{\"refkey\":\"{refkey}\",\"pdfUrl\":\"{location}\"}"
}
]
}
]
}
  • This only allows POST requests to the "callback" endpoint.
  • It will send a custom header always to identity the agent to the callback service. This might be used for logging on the callback server side.
  • The endpoint requires OAuth2 authentication using the OAuth2 password flow.
  • It will send a JSON request built from the payload value.
  • The placeholder {location} will be replaced by the actual url where to download the PDF.
  • The placeholder {refkey} points to a custom parameter that was sent with the original request that triggered the rendering.

Basic Request Properties

url

Full qualified base URI for this connection.

method

HTTP method to be used for queries to the endpoint.

  • Data Type: String (any of GET, POST, PUT, PATCH)
  • Default: (depends on worker)
    • GET (mediaproxy)
    • PUT (upload)
    • POST (callback, error)

Map of request headers

  • Data Type: object
  • Default: null

NOTE: These header will be set before applying computed headers like Content-Length, Authorization etc.

HINT: Headers allow variable expansion. Variable names must be enclosed by curly brackets. Which variables are available for expansion depends on the processing steps and may differ between say mediaproxy and upload process. Please, refer to the documentation of the worker.

Example
{
"url": "https://example.com/protected/images",
"method": "PUT",
"authentication": {
"type": "Bearer",
"value": "eyJmb28iOiJiYXIifQ=="
},
"header": {
"Content-Type": "application/octet-stream",
"x-ticket-id": "priintcloud ticket is {ticket}"
}
}

After variable expansion this may lead to a request like this

PUT /protected/images  HTTP/1.1
Host: https://example.com
Content-Type: application/octet-stream
x-ticket-id: priintcloud ticket is u6g3fzzv36nzswjdb6dzdiuvpy
Authorization: Bearer eyJmb28iOiJiYXIifQ==

HTTP Client Configuration

allow-insecure

  • Do not use this setting for priint cloud connections.
  • All connections to out-bound services MUST be secure (i.e. https_only).

connect-timeout

Connection timeout in seconds.

This is the time to wait for the connection to be established.

  • Data Type: int
  • Default: 5 (5 sec)

follow-redirects

Automatically redirect to an URI declared in 3xx responses.

  • Data Type: boolean
  • Default: false

request-timeout

Request timeout in seconds.

This is the time to wait for the response after the connection has been established.

  • Data Type: int
  • Default: 60 (1 min)

Caching Configuration

Clientside HTTP caching for GET requests.

NOTE: Cache configuration is specific to mediaproxy.

cache

  • Data Type: Object
  • Default: null

Example

{
"cache": {
"max-duration": 600,
// 1 h
"ignore-cache-control": true
}
}

cache.max-duration

Max age of an entry in the cache in seconds.

This is applied even if the Cache-Control headers of the response would allow for more.

  • Data Type: int (seconds)
  • Default: 0 (no caching)

cache.max-object-size

Objects exceeding this threshold will never be cached.

  • Data Type: long (number of bytes)
  • Default: 10485760 (10 MB)

cache.heuristic

Allow HttpClient to cache values without Cache-Control headers using the rules given in RFC-2616.

  • Data Type: boolean
  • Default: true

cache.revalidate-after

Currently not supported

cache.keys

currently not supported

cache.ignore-cache-control

Ignore the RFC-2616 standards compliant mode for caching.

Data will be cached regardless of the caching headers send by the client only on the base of max-duration setting.

  • Data Type: boolean
  • Default: false

Authentication Configuration

priint cloud supports the following authentication types.

NameDescription
-public access - no authentication necessary
BasicProtected by username and password.
BearerA token of type bearer is expected as HTTP Authorization Header. A static token is applied.
OAuth2A token of type bearer is expected as HTTP Authorization Header. The token is dynamically retrieved via a special request from an authorization server. Server endpoint, clientId and clientSecret must be defined in the configuration
ApiKeyAn API Key is expected in an HTTP Header. Header name and key are static values read from the configuration
AWSS3 authorization token is expected. This is a special variant of OAuth2 used by Amazon Web Services but also by Google Cloud Storage and other S3 compatible services. Dynamic headers are computed differing from chunk to chunk as the input it send to the receiving S3 server

Basic

Configuration example:

// "authentication": 
{
"type": "Basic",
"username": "foo",
"password": "bar"
}

Adding a header to all requests:

Authorization: Basic Zm9vOmJhcg

Supported properties are

  • type (must be Basic)
  • username (required)
  • password (required)

Bearer

Configuration example:

// "authentication": 
{
"type": "Bearer",
"value": "eyJmb28iOiJiYXIifQ=="
}

Adding a header to all requests:

Authorization: Bearer eyJmb28iOiJiYXIifQ==

Supported properties are

  • type (must be Bearer)
  • value (required)

OAuth2

Configuration example:

{
"authentication": {
"type": "OAuth2",
"grantType": "Password",
"accessTokenUrl": "https://iam.com/realms/example/oauth/v1/token",
"clientId": "wzJ5ge9v5LSUEv6nM8MeQEaFu4TxnaNe",
"clientSecret": "YjhNbkVGSlBxVEtmQXBYZzJzOVE4cUhVd2p5WTh2UGRjRlFGWTlkUHVMaDZqRXF0",
"username": "priintcloud-worker",
"password": "S*meS*cr*tCh*rs",
"scope": "readwrite"
}
}

If a valid token is already cached then a header is added to all requests like this:

Authorization: Bearer ValueOfMyOAuth2AccessToken

If there is no valid token yet, a sub-request is posted to the accessTokenUrl using the standard OAuth2 "password" flow to retrieve a OAuth2 token as JSON object.

# >>> request
POST {accessTokenUrl}
Content-Type: application/x-www-form-urlencoded
Accept: application/json
Authorization: Basic base64({clientId}:{clientSecret})

grant_type = password &
username = {username} &
password = {password} &
scope = {scope}

# <<< response
Content-Type: application/json

{
"access_token" : "Y2MyY2MxMjcxMDU5MDMxZWZiNWM1ODZiMTA5ZGE0NzZmZTk5NmJjMTFlOTg0NjFhYg",
"expires_in" : 3600,
"token_type" : "bearer",
"scope" : "readwrite",
"refresh_token" : "MxMjcxMDhNDNiMzMyZTNmZDMyZWEyOGEyYzFiN2M0NjBlNzAzMzhkYTMwYzU4ZTlhe"
}

Supported properties are

  • type (must be OAuth2)
  • grantType (must be ClientCredentials or Password)
    • ClientCredentials expects that clientId and clientSecret is set
    • Password expects that username and password is set - most often additionally to clientId and clientSecret
  • accessTokenUrl (required, full qualified URI)
  • clientId (optional)
  • clientSecret (optional)
  • username (optional)
  • password (optional)
  • scope (optional)

ApiKey

Configuration example:

{
"authentication": {
"type": "ApiKey",
"key": "MyFooApi",
"value": "eyJmb28iOiJiYXIifQ=="
}
}

Adding a header to all requests:

MyFooApi: eyJmb28iOiJiYXIifQ==

Supported properties are

  • type (must be ApiKey)
  • key (optional, defaults to ApiKey)
  • value (required)

AWS

Supporting S3 storage servers.

Configuration example:

{
"authentication": {
type: "AWS",
accessKey: "changeme",
secretKey: "changeme"
}
}

Supported properties are

  • type (must be AWS)
  • accessKey (required, consult your S3 documentation)
  • secretKey (required, consult your S3 documentation)

NOTE: AWS authentication is currently only supported for the upload step,

Request Payload Configuration

NOTE: Payload configuration is specific to webhooks.

payload

Payloads of HTTP requests can be configured via one payload template (standard single-part case) and multiple payloads templates (for multipart/form-data).

  • Data Type: Array of Payload objects
  • Default: null

In multipart/form-data request, each part must be represented as a separate payload object.

In all other cases, a single payload object with just a value property is required.

Example for simple JSON POST for callback worker

{
"header": {
"Content-Type": "application/json"
},
"payload": [
{
"value": "{\"status\":\"success\",\"location\":\"{location}\"}"
}
]
}

Example for multipart/form-data POST for upload worker

{
"header": {
"Content-Type": "multipart/form-data"
},
"payload": [
{
"mediaType": "application/json",
"fieldName": "input",
"value": "{\"status\":\"success\",\"ticketId\":\"{ticket}\"}"
},
{
"mediaType": "application/pdf",
"fieldName": "file",
"filename": "datasheet-{foreignKey}.pdf"
}
]
}

payload.mediaType

Content type of the request body (or body part).

  • Data Type: String
  • Default: null

payload.fieldName

Name of the body part.

Only used for content-type=multipart/form-data.

  • Data Type: String
  • Default: null

payload.filename

Set the filename in the content disposition header of the body part.

Only used for content-type=multipart/form-data.

In upload case, the PDF will be attached as the content of the body part.

ADVICE: The payload for the file upload part should be the last one in the array of payloads.

  • Data Type: String
  • Default: null

For more details see https://datatracker.ietf.org/doc/html/rfc7578#section-4.2.

HINT: If the filename of the payload is set, then the value property will be ignored.

payload.value

String containing a template for the payload.

NOTE: Payload configuration is specific to webhooks.

HINT: Payload values allow variable expansion. Variable names must be enclosed by curly brackets. Which variables are available for expansion depends on the processing steps and may differ between say callback and upload process. Please, refer to the documentation of the worker.

  • Data Type: String
  • Default: null

use-chunked-transfer

Deactivate chunked-transfer as default streaming procedure for uploads.

The default http exchange method of the upload process is 'chunked transfer' (see https://en.wikipedia.org/wiki/Chunked_transfer_encoding).

Not all receiving servers will support chunked transfer for uploads. Many blob stores, e.g., require knowing the total size of the upload in advance (which is not supported with chunked transfer).

  • Data Type: boolean
  • Default: true

FAQs

How to upload to Azure Blog Store ?

TOD

Hint: set use-chunked-transfer to false.

Upload to Google Cloud Storage

Use AWS authorization with clientId and clientSecret are created via Google console.