Request Interception

Aidbox Form Builder & Renderer Request Interception

Request interception allows you to modify network requests made by Aidbox Form Builder and Aidbox Form Renderer. This is useful for debugging, adding authentication, redirecting requests, or handling custom logic before requests are sent.

Enabling Request Interception

To enable request interception, set the enable-fetch-proxy attribute on the component and provide a custom fetch function:

html
<aidbox-form-builder id="aidbox-form-builder" enable-fetch-proxy />

<script>
    const builder = document.getElementById('aidbox-form-builder');
    
    builder.fetch = async (url, init) => {
        console.log('Intercepted request', url, init);
        return fetch(url, init);
    };
</script>
html
<aidbox-form-renderer id="aidbox-form-renderer" enable-fetch-proxy />

<script>
    const renderer = document.getElementById('aidbox-form-renderer');
    
    renderer.fetch = async (url, init) => {
        console.log('Intercepted request', url, init);
        return fetch(url, init);
    };
</script>

The interception function must follow the same signature as the standard fetch function, with the following exceptions:

  1. The function can return null or undefined to bypass the interception and allow the builder to handle the request using the standard fetch.
  2. 2. The init object (the second argument) may include an additional tag property. This tag is a string representing the name of one of the Request Interception, allowing you to differentiate between them without relying on the URL or HTTP method, which may be subject to future changes.

Common Use Cases

These examples demonstrate how to use request interception in various scenarios. Most of the examples are also applicable to the Renderer component.

1. Logging Requests

To inspect outgoing requests and responses:

html
<aidbox-form-renderer id="aidbox-form-renderer" enable-fetch-proxy />

<script>
    const renderer = document.getElementById('aidbox-form-renderer');
    
    renderer.fetch = async (url, init) => {
        console.log('Request:', url, init);
        const response = await fetch(url, init);
        console.log('Response:', response.status, await response.text());
        return response;
    };
</script>

2. Adding Authorization Headers

To include an authorization token in requests:

html
<aidbox-form-builder id="aidbox-form-builder" enable-fetch-proxy />

<script>
    const builder = document.getElementById('aidbox-form-builder');
    
    builder.fetch = async (url, init) => {
        const headers = new Headers(init.headers);
        headers.set('Authorization', `Bearer YOUR_ACCESS_TOKEN`);
        return fetch(url, { ...init, headers });
    };
</script>

3. Redirecting Requests

To change the endpoint of requests dynamically:

html
<aidbox-form-renderer id="aidbox-form-renderer" enable-fetch-proxy />

<script>
    const renderer = document.getElementById('aidbox-form-renderer');
    
    renderer.fetch = async (url, init) => {
        const newUrl = url.replace('aidbox-instance.com', 'custom-endpoint.com');
        return fetch(newUrl, init);
    };
</script>

4. Handling Custom Questionnaire Storage

To store and retrieve forms from local storage:

html
<aidbox-form-builder form-id="local-questionnaire" id="aidbox-form-builder" enable-fetch-proxy />

<script>
    const builder = document.getElementById('aidbox-form-builder');

    builder.fetch = async (url, init) => {
        if (init.tag === 'get-questionnaire') {
            const storedForm = localStorage.getItem('local-questionnaire') || '{"resourceType": "Questionnaire", "id": "local-questionnaire"}';
            return new Response(storedForm, { status: 200 });
        }
        if (init.tag === 'save-questionnaire') {
            localStorage.setItem('local-questionnaire', init.body);
            return new Response(init.body, { status: 200 });
        }
        return null;
    };
</script>

5. Modifying Extracted Data

To manipulate extraction results before they are processed:

html
<aidbox-form-builder id="aidbox-form-builder" enable-fetch-proxy />

<script>
    const builder = document.getElementById('aidbox-form-builder');
    
    builder.fetch = async (url, init) => {
        if (init.tag === 'extract') {
            const response = await fetch(url, init);
            const bundle = await response.clone().json();
            console.log('Extracted Bundle:', bundle);
            return response;
        }
        return null;
    };
</script>

Endpoints

assemble-questionnaire

Triggered after saving the current questionnaire, if it includes sub-questionnaires, to assemble the full questionnaire.

Request

http
POST /fhir/Questionnaire/$assemble HTTP/1.1 
Content-Type: application/json

{
    "resourceType": "Parameters",
    "parameter": [{
        "name": "questionnaire",
        "resource": <questionnaire>
    }]
}

Where is the questionnaire being assembled.

Response

json
<questionnaire>

Where is the assembled questionnaire.

assemble-sub-questionnaire-usages

Triggered after saving a sub-questionnaire to update all parent questionnaires that include it.

Request

http
POST /Questionnaire/$assemble-all HTTP/1.1 
Content-Type: application/json

{
    "questionnaires": [
        {
            "id": <questionnaire-1-id>,
            "resourceType": "Questionnaire"
        },
        {
            "id": <questionnaire-2-id>,
            "resourceType": "Questionnaire"
        },
        ...
    ]
}

Where , , etc., are the IDs of the parent questionnaires that include the sub-questionnaire.

Response

json
[
  <questionnaire-1>, 
  <questionnaire-2>, 
  ...
]

Where , , etc., are the updated questionnaires.

check-sub-questionnaire-usage

Triggered after saving a sub-questionnaire to verify if it is currently used in any parent questionnaires.

Request

http
GET /Questionnaire/<sub-questionnaire-id>/$usage HTTP/1.1 

Where is the ID of the sub-questionnaire.

Response

json
{
    "questionnaires": [
        {
            "id": <questionnaire-1-id>,
            "resourceType": "Questionnaire"
        },
        {
            "id": <questionnaire-2-id>,
            "resourceType": "Questionnaire"
        },
        ...
    ]
}

Where , , etc., are the IDs of the parent questionnaires that include the sub-questionnaire.

delete-assembled-questionnaire

Triggered after saving the current questionnaire, when the saved questionnaire no longer references sub-questionnaires.

Request

http
DELETE /sdc/Questionnaire?url=<questionnaire-url>&version=<questionnaire-version>-assembled HTTP/1.1

Where is the canonical URL and is the version of the questionnaire being deleted.

Response

json
<questionnaire>

Where is the questionnaire that was deleted.

delete-attachment

Triggered when the attachment input field is cleared.

Request

http
DELETE /$sdc-file/<filepath> HTTP/1.1

Where is the path of the attachment being deleted.

Response

Response shape is specific to the storage type and is not processed by the frontend.

extract

Triggered when the "Extract" button in the debug panel is clicked.

Request

http
POST /fhir/QuestionnaireResponse/$extract HTTP/1.1
Content-Type: application/json

{
    "resourceType": "Parameters",
    "parameter": [{
        "name": "questionnaireResponse",
        "resource": <questionnaire-response>
    }, {
        "name": "questionnaire",
        "resource": <questionnaire>
    }]
}

Where is the questionnaire response being extracted and is the questionnaire it is based on.

Response

json
<bundle>

Where is the bundle of resources extracted from the questionnaire response.

get-assembled-questionnaire

Triggered after retrieving the current questionnaire to obtain its fully assembled version, if it includes sub-questionnaires.

Request

http
GET /sdc/Questionnaire?url=<questionnaire-url>&version=<questionnaire-version>-assembled HTTP/1.1

Where represents the canonical URL, and specifies the version of the assembled questionnaire being requested.

Response

json
<bundle>

Where is the bundle containing zero or one questionnaire resource.

get-config

Triggered during the initialization of the builder or renderer to fetch configuration details.

Request

http
POST /$sdc-config HTTP/1.1
Content-Type: application/json

{
    "resourceType": "Parameters",
    "parameter": [{
        "name": "id",
        "valueString": "<config-id>"
    }]
}

Where refers to the ID of the SDCConfig resource included in the JWT token payload of the current authentication session. This parameter is omitted if no configuration is specified.

Response

json
<config>

Where is the Configuration resource containing the configuration details.

get-questionnaire

Triggered during the initialization of the builder or renderer to fetch the current questionnaire.

Request

http
GET /sdc/Questionnaire/<questionnaire-id> HTTP/1.1

Where is the ID of the questionnaire being requested.

Response

json
<questionnaire>

Where is the questionnaire being requested.

get-questionnaire-response

Triggered during the initialization of the renderer to fetch the current user response.

Request

http
GET /sdc/QuestionnaireResponse/<questionnaire-response-id> HTTP/1.1

Where is the ID of the questionnaire response being requested.

Response

json
<questionnaire-response>

Where is the questionnaire response being requested.

get-fhir-metadata

Triggered during the initialization of the builder to fetch metadata for FHIR resources, which aids in autocompletion.

Request

http
GET /fhir/metadata HTTP/1.1

Response

json
<fhir-metadata>

Where is the metadata for the FHIR server.

get-fhir-schemas

Triggered during the initialization of the builder to fetch schemas for FHIR resource elements, aiding in autocompletion.

Request

http
GET /static/fhir_schemas.json HTTP/1.1

Response

json
<fhir-schemas>

Where is the JSON object containing the schemas for the FHIR resource elements.

get-questionnaire-by-id

Triggered before saving the current questionnaire to check for conflicts with existing questionnaires.

Request

http
GET /sdc/Questionnaire/<questionnaire-id> HTTP/1.1

Where is the ID of the questionnaire being checked.

Response

json
<questionnaire>

Where is the questionnaire being checked.

get-theme

Triggered during the initialization of the web component if a theme is referenced in the configuration.

Request

http
GET /QuestionnaireTheme/<theme-id> HTTP/1.1

Where is the ID of the theme being requested.

Response

json
<theme>

Where is the Configuration being requested.

get-themes

Triggered during the initialization of the builder web component and after saving a theme to list available themes in the theme selector.

Request

http
GET /QuestionnaireTheme?_sort=.theme-name HTTP/1.1

Response

json
<bundle>

Where is the bundle of Configuration.

import-questionnaire

Triggered when the "Import" button is clicked in the questionnaire importer.

Request

http
POST /sdc/Questionnaire HTTP/1.1
Content-Type: application/json

<questionnaire>

Where is the questionnaire being imported.

Response

json
<questionnaire>

Where is the questionnaire that was imported.

populate

Triggered when the "Populate" button is clicked in the debug panel.

Request

http
POST /fhir/Questionnaire/$populate HTTP/1.1
Content-Type: application/json

{
    "resourceType": "Parameters",
    "parameter": [{
        "name": "questionnaire",
        "resource": <questionnaire>
    }, {
        "name": "subject",
        "valueReference": <patient-id>
    }, {
        "name": "local",
        "valueBoolean": true
    }, {
        "name": "context",
        "part": [{
            "name": "name",
            "valueString": "encounter"
        }, {
            "name": "content",
            "valueReference": <encounter-id>
        }, {
            "name": "name",
            "valueString": "author"
        }, {
            "name": "content",
            "valueReference": <patient-id>
        }]
    }]
}

Where is the questionnaire being populated, is the ID of the patient, and is the ID of the encounter selected in the debug panel. (todo: add explanation)

Response

json
<parameters>

Where is a parameters resource containing the populated questionnaire response under the response name.

save-response

Triggered by the auto-save mechanism shortly after the user makes changes in the form.

Request

http
POST /fhir/QuestionnaireResponse/$save HTTP/1.1
Content-Type: appliation/json

{
    "resourceType": "Parameters",
    "parameter": [{
        "name": "response",
        "resource": <questionnaire-response>
    }]
}

Where is the response being submitted.

Status Value

Since auto-save is only enabled for non-completed forms, the response parameter always has the status in-progress.

Response

json
<parameters>

Where is a parameters that includes:

  • response: the saved questionnaire response.
  • issues: any validation or processing issues, if available.

submit-response

Triggered when the user submits a response by clicking the submit button. The submit button is displayed when the questionnaire response is either in progress (in-progress) or when the user is amending a completed response.

Request

http
POST /fhir/QuestionnaireResponse/$submit HTTP/1.1
Content-Type: appliation/json

{
    "resourceType": "Parameters",
    "parameter": [{
        "name": "response",
        "resource": <questionnaire-response>
    }]
}

Where is the response being submitted.

Status Value

The response parameter contains the current status, and the Aidbox backend is responsible for transitioning it to the appropriate new state. Therefore, if you need to, for example, intercept an amending submission, you should check for the condition response.status = 'completed'.

Response

json
<parameters>

Where is a parameters that includes:

  • response: the processed questionnaire response.
  • issues: any validation or processing issues, if available.
  • outcome: a list of extracted resources when the questionnaire has extraction rules.

repopulate

Triggered when the "Repopulate" button is clicked by the user.

Request

http
POST /fhir/Questionnaire/$populate HTTP/1.1
Content-Type: application/json

{
    "resourceType": "Parameters",
    "parameter": [{
        "name": "questionnaire",
        "resource": <questionnaire>
    }, {
        "name": "response",
        "resource": <questionnaire-response>
    }, {
        "name": "subject",
        "valueReference": <patient-id>
    }, {
        "name": "local",
        "valueBoolean": true
    }, {
        "name": "context",
        "part": [{
            "name": "name",
            "valueString": "encounter"
        }, {
            "name": "content",
            "valueReference": <encounter-id>
        }]
    }]
}

Where , , , and are as described in the Request Interception request.

Response

json
<parameters>

Where is a parameters resource containing the repopulated questionnaire response under the response name.

save-assembled-questionnaire

Triggered after saving the current questionnaire, if it includes sub-questionnaires, to save the assembled version.

Request

http
PUT /sdc/Questionnaire?url=<questionnaire-url>&version=<questionnaire-version>-assembled HTTP/1.1
Content-Type: application/json

<assembled-questionnaire>

Where and are as described in the Request Interception request, and is the assembled questionnaire being saved.

Response

json
<questionnaire>

Where is the questionnaire that was saved.

validated-extracted-bundle

Triggered upon completion of an extract operation initiated by the "Extract" button in the debug panel.

Request

http
POST / HTTP/1.1
Content-Type: application/json

<bundle>

Where is the bundle containing resources obtained from Request Interception.

Response

json
<bundle>

Where is the bundle of saved resources.

create-questionnaire

Triggered when the "Save" button is clicked in the builder for a new questionnaire.

Request

http
POST /sdc/Questionnaire HTTP/1.1
Content-Type: application/json

<questionnaire>

Where is the new questionnaire being created.

Response

json
<questionnaire>

Where is the questionnaire that was created.

save-questionnaire

Triggered when the "Save" button is clicked in the builder.

Request

http
PUT /sdc/Questionnaire/<questionnaire-id> HTTP/1.1
Content-Type: application/json

<questionnaire>

Where is the questionnaire being saved.

Response

json
<questionnaire>

Where is the questionnaire that was saved.

create-sub-questionnaire

Triggered when an outline item is saved as a sub-questionnaire.

Request

http
POST /sdc/Questionnaire?url=<sub-questionnaire-url>&version=1 HTTP/1.1
Content-Type: application/json

<sub-questionnaire>

Where is the canonical URL of the sub-questionnaire and is the sub-questionnaire being saved.

Response

json
<sub-questionnaire>

Where is the questionnaire that was created.

create-theme

Triggered when the "Save" button is clicked in the theme editor for a new theme.

Request

http
POST /QuestionnaireTheme HTTP/1.1
Content-Type: application/json

<theme>

Where is the new theme being created.

Response

json
<theme>

Where is the Configuration being created.

save-theme

Triggered when the "Save" button is clicked in the theme editor.

Request

http
PUT /QuestionnaireTheme/<theme-id> HTTP/1.1
Content-Type: application/json

<theme>

Where is the theme being saved.

Response

json
<theme>

Where is the Configuration being saved.

search-choice-options

Triggered when dropdown options are requested for a choice item.

Request

http
GET <url> HTTP/1.1

Where is the URL of the value set or resources associated with the choice item.

Response

Response be a plain list or bundle of resources (e.g. ValueSet) depending on the source of the options.

search-questionnaires-by-url

Triggered before saving the current questionnaire to check for conflicts with existing questionnaires based on their URL.

Request

http
GET /sdc/Questionnaire?url=<questionnaire-url> HTTP/1.1

Where is the canonical URL of the questionnaire being checked.

Response

json
<bundle>

Where is the bundle of questionnaires with the same URL.

search-sub-questionnaires

Triggered when the user searches for sub-questionnaires in the builder.

Request

http
GET /sdc/Questionnaire?.extension$contains=%-child&.title$contains=<search-term> HTTP/1.1

Where is the term being searched for.

Response

json
<bundle>

Where is the bundle of sub-questionnaires.

get-sub-questionnaire

Triggered to retrieve a sub-questionnaire when it is referenced in a parent questionnaire.

Request

http
GET /sdc/Questionnaire?url=<sub-questionnaire-url>&version=<sub-questionnaire-version> HTTP/1.1

Where is the canonical URL of the sub-questionnaire being requested. Parameter version is omitted if no version is specified in the reference.

Response

json
<bundle>

Where is the bundle containing zero or one questionnaire resource.

upload-attachment

Triggered when a file is selected in the attachment input field.

Request

http
POST /$sdc-file HTTP/1.1 
Content-Type: multipart/form-data; boundary=------------------------boundary12345

--------------------------boundary12345
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain

<file-content>
--------------------------boundary12345
Content-Disposition: form-data; name="filename"

<file-name>
--------------------------boundary12345--

Where is the content of the file being uploaded and is the path and name of the file.

Response

json
{
  "url": "<file-url>"
}

Where is the URL of the uploaded file which will further be used to either download or Request Interception the file.

validate-questionnaire

Triggered when the "Validate Questionnaire" button is clicked in the debug panel.

Request

http
POST /Questionnaire/$validate HTTP/1.1
Content-Type: application/json

<questionnaire>

Where is the questionnaire being validated.

Response

json
<operation-outcome>

Where is the operation outcome of the validation.

validate-response

Triggered when the "Validate Questionnaire Response" button is clicked in the debug panel.

Request

http
POST /QuestionnaireResponse/$validate HTTP/1.1
Content-Type: application/json

<questionnaire-response>

Where is the response being validated.

Response

json
<operation-outcome>

Where is the operation outcome of the validation.