> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/web/webviewer-server/wv-server-usage.md).

# Optimize / customize WebViewer Server usage

Enhance WebViewer Server performance with optimal usage tips. Learn to customize server settings for seamless client experiences on web. Boost efficiency with caching, performance tweaks, and document

## Normal Usage

WebViewer Server is designed to work hand-in-hand with the WebViewer client in order to seamlessly optimize the viewing experience. Once the server is running, simply supply the `webviewerServerURL` argument to WebViewer upon startup:

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
options.webviewerServerURL = 'http://<docker_address>'
WebViewer(options, viewerElement);
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
options.pdftronServer = 'http://<docker_address>'
WebViewer(options, viewerElement);
```

{% endcode %}
{% endtab %}
{% endtabs %}

This will ensure an optimal client experience on any of your target platforms, optimizing the delivery method as required.

## Caching and Performance

In order to handle requests as quickly as possible with minimal server load, WebViewer Server caches intermediate data opportunistically. For example, this might include includes caching parsed PDF content in memory for quick re-renders of the same doc, caching conversion results, fetched data, and render tiles, if used.

It will also batch requests together in order to minimize cpu-heavy operations like conversions -- if users Alice and Bob try to view the same Word document at the same time, then only one conversion to PDF will ever take place, and the will be broadcast to both users. For documents under high contention (as might happen when sharing a doc for review), the performance benefit can be tremendous.

In order for this caching and batching to work correctly, the server requires that incoming URLs map to documents in a one-to-one manner, including query parameters. If Alice and Bob access the same document but via different URLs, then the server will assume they are different documents and end up doing more work than is required. In order to ensure the cache is working as intended, it may be necessary to move unique URL query parameters (access tokens and time stamps, for example) into the request headers instead.

### Controlling the Document Cache with CacheKey

We also offer method of controlling caching on the WebViewer Server. When requesting documents you can pass a `cacheKey` to the load document call. This will cause the document requested to be cached on the `cacheKey` you have provided. If a request is ever made to this `cacheKey`, the document first cached under that key will be returned.

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
WebViewer(...)
  .then(instance => {
    const options = {
      cacheKey: "unique_id_entry123",
    };
    const url = 'http://<documentserver>/FileDownload?param1=abcd&fetchid=dcba';
    instance.loadDocument(url, options);
  });
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Server authentication

When a document URL is provided to WebViewer, that URL will now be fetched by the docker server instead of the browser. If authorization information needs to be provided to the server providing the document, this can be done using the `customHeaders` option when creating a document.

You can also provide the `filename` option to ensure that the server knows what type of file you are attempting to view (in case it is not clear from the URL).

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
WebViewer(...)
  .then(instance => {
    const options = {
      customHeaders: { Cookie: "MYAUTHTOKEN=BF6CF50AB90C4025" },
      filename: "Document.pdf"
    };
    const url = 'http://<documentserver>/FileDownload?param1=abcd&fetchid=dcba';
    instance.loadDocument(url, options);
  });
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

When the docker server makes a request to fetch `http://<documentserver>/FileDownload?param1=abcd&fetchid=dcba`, the http request will include the values in `options.customHeaders`.

### Custom Query Parameters

It is also possible to append a query parameter onto every request made to and from WebViewer Server. This can be used as a form of authentication or to handle some other system. To do so, call `loadDocument` with your custom query parameters like so:

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
instance.loadDocument('http://pdftron.com/mydocument.pdf', { 
  webViewerServerCustomQueryParameters: { param1: 'param1data', param2: 'param2data'}
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

Now every link will have `param1` and `param2` appended to it as a query parameter.

## Extended API

For most use cases no extra interaction with the server is required, beyond what is mentioned in the previous section. For special cases, these endpoints can be used to further optimize your application, or tailor it to your own particular use case

#### `PreloadURL`

Preload a document into WebViewer server prior to actually viewing it.

**Parameters**

| Name  | Type   | Description                                                                        |
| ----- | ------ | ---------------------------------------------------------------------------------- |
| `url` | string | The URL of the document to be preloaded, should be a fully qualified absolute path |

**Returns**

Returns code 200 once the information has been received by the server. The response is asynchronous -- the return does not indicate that all preload work has been completed.

**Example**

For example, to pre-fetch `http://domain/document.pdf`, make a GET request to `http://<docker_address>/blackbox/PreloadURL?url=http%3A%2F%2Fdomain%2Fdocument.pdf`

#### `Metrics`

`GET myserver/blackbox/metrics`

Returns metric data for Prometheus.

**Returns**

* **response code 200** - Returns the metric data in the Prometheus format

**Example**

You can use this API with Prometheus by setting a target in Prometheus to it. Prometheus will then scrape the APIs as defined in our configuration docs.

#### `HealthCheck`

`GET myserver/blackbox/HealthCheck`

Checks whether your server is still able to process jobs. WebViewer Server tests at 30 second intervals as to whether it can process a document and updates the result of this check.

**Returns**

* **response code 200** - the server is up and working
* **response code 503** - the server is down

**Example**

For example, to check the state of your server, make a GET request to `http://<docker_address>/blackbox/HealthCheck`

#### `GetPerfInfo`

`GET myserver/blackbox/GetPerfInfo`

GetPerfInfo returns the queue latency (how long it takes to start working on any new work item) averaged over different timescales.

If the queue is momentarily held up by work items during usage, this is normal, and would show up as fluctuating values at small timescales (with larger timescales staying pretty steady)

If the queue is blocked due to work items with very heavy compute load or other reasons, it would manifest as all timescales rising steadily.

**Returns**

Returns a JSON object containing the queue times for each timescale.

**response code 200**

{% tabs %}
{% tab title="JSON" %}
{% code lineNumbers="true" %}

```json
{"queueTime": [ 500ms timescale, 2s timescale, 5s timescale, 30s timescale, 60s timescale ]
    "errorRate": [ unused ]
    "systemInfo": {
      "memoryData":{"total":value in mb,"available":value in mb},
      "diskData":{"total":value in GB,"free":value in GB},
      "heapSize":value in MB,
      "heapMaxSize":value in MB,
      "server_id":unique id,
      "os_info": operating system,
      "convert_queue_length": number of items queued for converting,
      "fetch_queue_length": number of items queued for fetching,
      "main_queue_length": number of items queued for all other types of work,
      "cpu_load": value (percentage of total),
      }
    }
```

{% endcode %}
{% endtab %}
{% endtabs %}

**Example**

For example, to check the state of your work queue, access `http://domain/document.pdf`, make a GET request to `http://<docker_address>/blackbox/GetPerfInfo`

#### `GetSupportedFormats`

`GET myserver/blackbox/GetSupportedFormats`

Get the currently supported formats by the server. Will return the formats in a JSON array. Any formats not listed by this API will be rejected by the server. Requires 1.5.7 or greater.

**Returns**

* **response code 200** - will return the allowed server formats in a JSON array

**Example**

**curl localhost:8090/blackbox/GetSupportedFormats**

#### `GetPDF`

`GET myserver/blackbox/GetPDF`

GET request to convert a document to PDF format, and return the result.

**Parameters**

| Name             | Type    | Description                                                                                                                                                                                     |
| ---------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `uri`            | string  | The URI of the document to be converted, should be a fully qualified absolute path. Required.                                                                                                   |
| `ext`            | string  | For usage when the file you wish to use GetPDF with is not a PDF. Specify the format of the file you wish to convert to PDF.                                                                    |
| `fmt`            | string  | The return format, if set to "data", will redirect to the actual pdf document, otherwise will return json data in the form `[{"uri":"<location of the pdf>"}]`                                  |
| `linearize`      | boolean | If set to 'true', will linearize the returned document.                                                                                                                                         |
| `xfdf`           | string  | The raw annotation data you wish to merge in with the document when performing the GetPDF job. This is expected in the XFDF format. **Requires a POST request instead of a GET request**.       |
| `PDFTron-Custom` | string  | A HTTP header which can be set with a JSON object containing custom headers like so: — The custom headers will be used when the server fetches the document requested through the uri argument. |
| `cacheKey`       | string  | The key to cache the document against. This will force the server to always return the same cached item corresponding to the cacheKey passed.                                                   |

**Returns**

* If `fmt` is set to "data", returns the converted PDF data.
* Otherwise returns a url to the converted result, relative to `http://<docker_address>/blackbox/`. This result is in json: `[{"uri":"<location of the pdf>"}]`
* In the case where this functionality has not been licensed, will return code 403 (forbidden).

**Example**

To obtain `http://domain/document.docx` in PDF format, access , make a GET request to `http://<docker_address>/blackbox/GetPDF?uri=http%3A%2F%2Fdomain%2Fdocument.docx&fmt=data&ext=docx`

To instead obtain a json formated link to the conversion result, make a GET request to `http://<docker_address>/blackbox/GetPDF?uri=http%3A%2F%2Fdomain%2Fdocument.docx`

#### Changing the result URL download name

If you wish for the result from GetPDF to be saved with a different name than it has and downloaded directly, set the query parameters on the download link `attach=true` and `dlname` to the name you wish to give the file. The example below shows how this would be done:

`http://localhost:8090/data/Converted/Fetched/myfile228288ccc.pdf?attach=true&dlname=mynewdocumentname.pdf`

#### `CacheCheck`

`GET myserver/blackbox/CacheCheck`

Check if a document was already cached by WebViewer Server.

The parameters used should match the options used by the document when it was originally cached. The parameter options are as follows. **Parameters will effect whether the cache finds the document.**

**Parameters**

| Name            | Type   | Description                                                                                                     |
| --------------- | ------ | --------------------------------------------------------------------------------------------------------------- |
| `uri`           | string | **Required** — The URL for the file. This can be a `cid://url` in the case of file uploads, or an internet url. |
| `ext`           | string | The manually specified extension of the file.                                                                   |
| `password`      | string | The password used for the file.                                                                                 |
| `cacheKey`      | string | The cacheKey used for the file.                                                                                 |
| `officeOptions` | string | The officeOptions used for the file.                                                                            |
| `cadOptions`    | string | The CAD options used for the file.                                                                              |
| `rastOptions`   | string | The rasterizer options used for the file.                                                                       |

**Returns**

Returns 200 if the document was cached, 404 if it was not.

**Example**

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
const request = new XMLHttpRequest();
  const docUrl = 'https://pdftron.s3.amazonaws.com/downloads/pl/webviewer-demo.pdf';
  let url = joinPaths('https://demo.apryse.com/blackbox/CacheCHeck?uri=' + encodeURIComponent(docUrl) + "&password=mypassword");
  request.open('GET', url);
  request.onreadystatechange = () => {
    if (request.readyState === 4) {
      try {
        if (request.status === 200) {
          console.log("Success")
        } else {
          //error
        }
      } catch (e) {
        //error
      }
    }
  };
  request.send();
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### `GetThumb`

`GET myserver/blackbox/GetThumb`

**Retrieve an image version of a PDF page. Allows the retrieving of files that can be used as thumbnails or previews.**

**Parameters**

| Name             | Type    | Description                                                                                                                                                                                     |
| ---------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `uri`            | string  | The URI of the document to be converted, should be a fully qualified absolute path                                                                                                              |
| `page`           | string  | The page to render, with page 0 representing the first page.                                                                                                                                    |
| `size`           | string  | The size of the thumbnail expected. Accepts `large` (1280p) `medium` (640p) and `small` (320p)                                                                                                  |
| `ext`            | string  | For usage when the file you wish to use GetThumb with is not a PDF. Specify the format of the file you wish to generate a thumbnail for.                                                        |
| `renderAnnots`   | boolean | Defaults to false, if set to true includes annotations on thumbnail                                                                                                                             |
| `PDFTron-Custom` | string  | A HTTP header which can be set with a JSON object containing custom headers like so: — The custom headers will be used when the server fetches the document requested through the uri argument. |

**Returns**

Returns code 200 if the image render was successful and returns json containing the URI to the image file in the format:

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
{
  [uri: 'https://pdftron.com/document.pdf']
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

**Example**

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
const request = new XMLHttpRequest();
  const docUrl = 'https://pdftron.s3.amazonaws.com/downloads/pl/webviewer-demo.pdf';
  const page = 0;
  const size = 'large';
  let url = joinPaths('https://demo.apryse.com/blackbox/GetThumb?uri=' + encodeURIComponent(docUrl) + "&page=" + page + "&size=" + size);
  request.open('GET', url);
  request.withCredentials = true;
  request.onreadystatechange = () => {
    if (request.readyState === 4) {
      try {
        if (request.status === 200) {
          const data = JSON.parse(request.responseText);
          for (let i = 0; i < data.length; i++) {
            if(data[i].uri){
              ///do something with thumb
            }
          }
        } else {
          //error
        }
      } catch (e) {
        //error
      }
    }
  };
  request.send();
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/web/webviewer-server/wv-server-usage.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
