---

uuid: 723afcbb-118d-433e-8ab4-560ffca93582

type:
- TestCase

name: |
  Outbox Servers handling activity submissions MUST return a 201 created HTTP status code

slug: |
  outbox-post-servers-must-return-a-201-created-http-code

description: |
  This test checks that an ActivityPub Outbox responds with a 201 status code when sent a POST request with an Activity submission.

testsRequirement:
- id: urn:uuid:3b925cdf-89fe-4f51-b41f-26df23f58e0c
  url: https://socialweb.coop/activitypub/behaviors/3b925cdf-89fe-4f51-b41f-26df23f58e0c
  name: Servers MUST return a 201 Created HTTP code

# https://www.w3.org/QA/WG/2005/01/test-faq#review
# *submitted, accepted, reviewed*, *returned for revision*, or *rejected*
testCaseState: submitted

respec:
  config:
    format: markdown
    editors:
    - name: "Benjamin Goering"
      company: "bengo.is"
      companyURL: "https://bengo.is"
---

# Outbox Servers handling activity submissions MUST return a 201 created HTTP status code

## Background

In the context of [client-to-server interactions](https://www.w3.org/TR/activitypub/#client-to-server-interactions) via Activity submission, [ActivityPub][activitypub] says
> Servers MUST return a 201 Created HTTP code

[activitypub]: https://www.w3.org/TR/activitypub/

## About this Test

This is a Test describing a rule to determine whether an ActivityPub Server is in conformance with the following behaviors required by [ActivityPub][activitypub]:

* Servers MUST return a 201 Created HTTP code aka [requirement 3b925cdf-89fe-4f51-b41f-26df23f58e0c](https://socialweb.coop/activitypub/behaviors/3b925cdf-89fe-4f51-b41f-26df23f58e0c)

### Identifier

The identifier of this test is `723afcbb-118d-433e-8ab4-560ffca93582`.

## Test Subject

The subject of this test is an ActivityPub Server serving activity submission requests for an ActivityPub Outbox.

The Test Subject can be identified by a URI for an ActivityPub Outbox. The ActivityPub Outbox has an `id` property and the ActivityPub server is responsible for responding to requests sent to it.

## Inputs

This test requires the following [inputs](https://www.w3.org/TR/act-rules-format/#input):

1. `outbox` - identifier of an ActivityPub Outbox
    * required: yes
    * type: binary
      * constraints
        * MUST be a URI, i.e. an [ActivityPub Object Identifier](https://www.w3.org/TR/activitypub/#obj-id) that is not `null`

2. `authorization` - proof of authorization to submit an activity to the outbox identified by input `outbox`
    * required: no
      * if this input is omitted, no `Authorization` header will be provided in the HTTP request send by this test
    * type: binary
      * constraints
        * If present, this should be valid as the value of an HTTP `Authorization` header

3. `submission` - ActivityPub message that will be submitted to the Outbox.
    * required: no
      * if this input is omitted, the test will use a simple valid submission
    * type: binary
      * constraints
        * should be JSON
      * note
        * this will be sent as the HTTP request body of an ActivityPub [client-to-server](https://www.w3.org/TR/activitypub/#client-to-server-interactions) request with header `Content-Type: application/ld+json; profile="https://www.w3.org/ns/activitystreams"`.

## Applicability

This test applies to the server hosting the ActivityPub Outbox identified by input `outbox`.

If input `outbox` is not a URI, outcome is `inapplicable`.

If input `outbox` URI scheme is not `https` or `http`, outcome is `inapplicable`. (This test may be revised later to handle other URI schemes).

### Test Targets

* `response` - the HTTP response that is the result of submitting the input `submission` to the ActivityPub Outbox identified by input `outbox`.
    * how to derive `response` from inputs
      1. start a timer with duration from input `time`. If the timer reaches zero before this derivation is complete, the whole test outcome is `inapplicable` because we weren't able to determine the `response` test target within the required time.
      2. let `request` be a new HTTP Request whose URI is input `outbox`
      3. add an http request header to `request` whose name is `Content-Type` and whose value is `application/ld+json; profile="https://www.w3.org/ns/activitystreams"`
      4. if input `authorization` was provided, add an http request header to `request` whose name is `Authorization` and whose value is input `authorization`
      5. let `submission` be the input `submission`, if provided, otherwise use the json value

          ```json
          {
            "@context": "https://www.w3.org/ns/activitystreams",
            "type": "Note",
            "content": "Say, did you finish reading that book I lent you?"
          }
          ```

      6. let the http request body of `request` be the value of `submission`
      7. send the HTTP request and await a response
      8. assign the HTTP response to the `response` test target

## Expectations

* `response` http status code is `201`

## Assumptions

### Default Outbox Submission

If an input `submission` is not provided, the test will use an activity based on Example 2 in [ActivityPub](https://www.w3.org/TR/activitypub/). If this causes problems, provide an input `submission` that will work to produce a 201 response status code and satisfy the requirement being tested.

## Test Cases

These are test cases for this test itself, i.e. each test case is a set of test inputs and the corresponding test results.

1. simple passed case

    * inputs
        * `outbox`

          ```url
          https://socialweb.coop/activitypub/testing/utilities/response?status=201`
          ```

        * `submission`

            ```json
            {
              "type": "Create"
            }
            ```

    * test targets
        * `response`

          ```http
          HTTP/2 201 
          content-type: application/json; charset=UTF-8

          {}
          ```

2. nginx 404 response body
    * outcome: `failed`
      * rationale: test target `response` does not meet expectation of its http status code being `201`
    * inputs
        * `outbox`: `'https://example.com/404'`
    * test targets
        * `response`:

          ```http
          HTTP/2 404 
          content-type: text/html; charset=UTF-8
          content-length: 153

          <html>
          <head><title>404 Not Found</title></head>
          <body>
          <center><h1>404 Not Found</h1></center>
          <hr><center>nginx/1.25.2</center>
          </body>
          </html>
          ```

3. non-URI input `outbox`
    * outcome: `inapplicable`
      * rationale: input `outbox` is not a URI
    * inputs
        * `outbox`: `bafybeib5mvfjatmpswc3jnh7ydz4zxe25cm63xp6aafpg3j2awakf63qma`

## Glossary

### `outcome`

An outcome is a conclusion that comes from evaluating a test on a test subject. An outcome can be one of the three following types:

* `inapplicable`: No part of the test subject matches the applicability
* `passed`: A test target meets all expectations
* `failed`: A test target does not meet all expectations

## Requirements Mapping

* [ActivityPub requirement 3b925cdf-89fe-4f51-b41f-26df23f58e0c](https://socialweb.coop/activitypub/behaviors/3b925cdf-89fe-4f51-b41f-26df23f58e0c) - Servers MUST return a 201 Created HTTP code
    * Required for Conformance to [ActivityPub][activitypub]
    * Outcome Mapping
        * when test target `response` has outcome `passed`, further testing is needed to determine requirement satisfaction
        * when test target `response` has outcome `failed`, requirement is not satisfied
        * when test target `response` has outcome `inapplicable`, further testing is needed to determine requirement satisfaction

## Issues

* [x] host an example outbox that can be used as the `passed` test case for this
    * it should always respond with http response 201
    * 2023-12-22T18:20:55.076Z: done: <https://socialweb.coop/activitypub/testing/utilities/response?status=201>
