Skip to content

Commit ce2fa30

Browse files
committed
Documentation for httpMalformedRequestTests
1 parent 4fd38fc commit ce2fa30

File tree

2 files changed

+286
-2
lines changed

2 files changed

+286
-2
lines changed

docs/source/1.0/spec/http-protocol-compliance-tests.rst

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ are used to make assertions about client and server protocol implementations.
3030
Used to define how an HTTP response is serialized given a specific
3131
protocol, authentication scheme, and set of output or error parameters.
3232

33+
Additionally, it defines one trait specifically for the behavior of server
34+
protocol implementations.
35+
36+
:ref:`smithy.test#httpMalformedRequestTests <httpMalformedRequestTests-trait>`
37+
Used to define how a server rejects a malformed HTTP request given a
38+
specific protocol and HTTP message.
39+
3340
Protocol implementation developers use these traits to ensure that their
3441
implementation is correct. This can be done through code generation of test
3542
cases or by dynamically loading test cases at runtime. For example, a Java
@@ -670,4 +677,281 @@ that uses :ref:`HTTP binding traits <http-traits>`.
670677
}
671678

672679

680+
.. smithy-trait:: smithy.test#httpMalformedRequestTests
681+
.. _httpMalformedRequestTests-trait:
682+
683+
-------------------------
684+
httpMalformedRequestTests
685+
-------------------------
686+
687+
Summary
688+
The ``httpMalformedRequestTests`` trait is used to define how a malformed
689+
HTTP request is rejected given a specific protocol and HTTP message.
690+
Protocol implementations MUST assert that requests are rejected during
691+
request processing.
692+
693+
Trait selector
694+
.. code-block:: none
695+
696+
operation
697+
Value type
698+
``list`` of ``HttpMalformedRequestTestCase`` structures
699+
700+
The ``httpMalformedRequestTests`` trait is a list of
701+
``HttpMalformedRequestTestCase`` structures that support the following members:
702+
703+
.. list-table::
704+
:header-rows: 1
705+
:widths: 10 25 65
706+
707+
* - Property
708+
- Type
709+
- Description
710+
* - id
711+
- ``string``
712+
- **Required**. The identifier of the test case. This identifier can
713+
be used by protocol test implementations to filter out unsupported
714+
test cases by ID, to generate test case names, etc. The provided
715+
``id`` MUST match Smithy's :token:`smithy:identifier` ABNF. No two
716+
``httpMalformedRequestTests`` test cases can share the same ID.
717+
* - protocol
718+
- shape ID
719+
- **Required**. A shape ID that targets a shape marked with the
720+
:ref:`protocolDefinition-trait`. Because Smithy services can support
721+
multiple protocols, each test MUST specify which protocol is under
722+
test.
723+
* - request
724+
- :ref:`HttpMalformedRequestDefinition <HttpMalformedRequestDefinition-struct>`
725+
- **Required**. A structure that describes the request.
726+
* - response
727+
- :ref:`HttpMalformedResponseDefinition <HttpMalformedResponseDefinition-struct>`
728+
- **Required**. A structure that describes the required response.
729+
* - documentation
730+
- ``string``
731+
- A description of the test and what is being asserted defined in
732+
CommonMark_.
733+
* - tags
734+
- ``[string]``
735+
- Attaches a list of tags that allow test cases to be categorized and
736+
grouped.
737+
738+
Using tags to describe types of failures gives implementations control
739+
of test execution across different suites of tests. For example, it
740+
allows tests to be executed that exercise booleans being converted into
741+
numerics, even if there are such tests written for values appearing in
742+
paths, query strings, headers, and message bodies across different
743+
protocols.
744+
* - testParameters
745+
- ``map<string, list<string>>``
746+
- Optional parameters that are substituted into each member of
747+
``request``, ``response``, as well as the test's ``tags`` and
748+
``documentation``.
749+
750+
The lists of values for each key must be identical
751+
in length. One test permutation is generated for each index the
752+
parameter lists. For example, parameters with 5 values for each key
753+
will generate 5 tests in total.
754+
755+
Parameter values are substituted using the conventions described by
756+
the documentation for CodeWriter_. They are available as named
757+
parameters, and implementations must support both the ``L`` and ``S``
758+
formatters.
759+
760+
.. note::
761+
762+
If ``testParameters`` is not null or empty, then substitution
763+
is performed on every string in ``request`` and ``response``
764+
even when there is no substitution requested. This means that
765+
explicit `$` characters must be represented as `$$` so as to not be
766+
interpreted as substitution expressions by the code generator.
767+
768+
.. _HttpMalformedRequestDefinition-struct:
769+
770+
HttpMalformedRequestDefinition
771+
==============================
772+
773+
.. list-table::
774+
:header-rows: 1
775+
:widths: 10 25 65
776+
777+
* - Property
778+
- Type
779+
- Description
780+
* - method
781+
- ``string``
782+
- **Required**. The HTTP request method.
783+
* - uri
784+
- ``string``
785+
- **Required**. The request-target of the HTTP request, not including
786+
the query string (for example, "/foo/bar").
787+
* - host
788+
- ``string``
789+
- The host or endpoint provided as input used to generate the HTTP
790+
request (for example, "example.com").
791+
* - queryParams
792+
- ``list<string>``
793+
- A list of the serialized query string parameters to include in the
794+
request.
795+
796+
Each element in the list is a query string key value pair
797+
that starts with the query string parameter name optionally
798+
followed by "=", optionally followed by the query string
799+
parameter value. For example, "foo=bar", "foo=", and "foo"
800+
are all valid values.
801+
802+
.. note::
803+
804+
This kind of list is used instead of a map so that query string
805+
parameter values for lists can be represented using repeated
806+
key-value pairs.
807+
808+
The query string parameter name and the value MUST appear in the
809+
format in which it is expected to be sent over the wire; if a key or
810+
value needs to be percent-encoded, then it MUST appear
811+
percent-encoded in this list.
812+
* - headers
813+
- ``map<string, string>``
814+
- A map of HTTP headers to include in the request. Each key represents a
815+
header field name and each value represents the expected header value.
816+
* - body
817+
- ``string``
818+
- The HTTP message body to include in the request. Because the ``body``
819+
parameter is a string, binary data MUST be represented in ``body`` by
820+
base64 encoding the data (for example, use "Zm9vCg==" and not "foo").
821+
822+
.. _HttpMalformedResponseDefinition-struct:
823+
824+
825+
HttpMalformedResponseDefinition
826+
===============================
827+
828+
.. list-table::
829+
:header-rows: 1
830+
:widths: 10 25 65
831+
832+
* - Property
833+
- Type
834+
- Description
835+
* - headers
836+
- ``map<string, string>``
837+
- A map of expected HTTP headers. Each key represents a header field
838+
name and each value represents the expected header value. An HTTP
839+
response is not in compliance with the protocol if any listed header
840+
is missing from the serialized response or if the expected header
841+
value differs from the serialized response value.
842+
843+
``headers`` applies no constraints on additional headers.
844+
* - code
845+
- ``integer``
846+
- **Required**. The expected HTTP response status code.
847+
* - body
848+
- :ref:`HttpMalformedResponseBodyDefinition <HttpMalformedResponseBodyDefinition-struct>`
849+
- The expected response body.
850+
851+
.. _HttpMalformedResponseBodyDefinition-struct:
852+
853+
854+
HttpMalformedResponseBodyDefinition
855+
-----------------------------------
856+
857+
.. list-table::
858+
:header-rows: 1
859+
:widths: 10 25 65
860+
861+
* - Property
862+
- Type
863+
- Description
864+
* - assertion
865+
- :ref:`HttpMalformedResponseBodyAssertion <HttpMalformedResponseBodyAssertion-union>`
866+
- **Required**. The assertion to be applied to the response body.
867+
* - mediaType
868+
- ``string``
869+
- **Required**. The media type of the ``body``. This is used to help test
870+
runners to parse and validate the expected data against generated data.
871+
Binary media type formats require that the contents of ``body`` are
872+
base64 encoded.
873+
874+
.. _HttpMalformedResponseBodyAssertion-union:
875+
876+
HttpMalformedResponseBodyAssertion
877+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
878+
879+
A union describing the assertion to run against the response body. As it is a
880+
union, exactly one member must be set.
881+
882+
.. list-table::
883+
:header-rows: 1
884+
:widths: 10 25 65
885+
886+
* - Property
887+
- Type
888+
- Description
889+
* - contents
890+
- ``string``
891+
- Defines the expected serialized response body, which will be matched
892+
exactly.
893+
* - messageRegex
894+
- ``string``
895+
- A regex to evaluate against the ``message`` field in the response body.
896+
For responses that may have some variance from platform to platform,
897+
such as those that include messages from a parser.
898+
899+
HTTP malformed request example
900+
==============================
901+
902+
The following example defines a malformed request test for a JSON protocol
903+
that uses :ref:`HTTP binding traits <http-traits>`. In this example, the server
904+
is rejecting many different variants of invalid numerics, and uses
905+
``testParameters`` to test three different invalid values, and tags each test
906+
with a descriptive string that allows implementations to run, or skip,
907+
specific types of malformed values.
908+
909+
.. code:: smithy
910+
911+
namespace smithy.example
912+
913+
use smithy.test#httpMalformedRequestTests
914+
@http(method: "POST", uri: "/InvertNumber/{numberValue}")
915+
@httpMalformedRequestTests([
916+
{
917+
id: "MalformedLongsInPathsRejected",
918+
documentation: """
919+
Malformed values in the path should be rejected""",
920+
protocol: exampleProtocol,
921+
request: {
922+
method: "POST",
923+
uri: "/InvertNumber/$value:L"
924+
},
925+
response: {
926+
code: 400,
927+
headers: {
928+
"errorType": "BadNumeric"
929+
},
930+
body: {
931+
assertion: {
932+
contents: """
933+
{"errorMessage": "Invalid value \"$value:L\""}"""
934+
},
935+
mediaType: "application/json"
936+
}
937+
938+
},
939+
testParameters : {
940+
"value" : ["true", "1.001", "2ABC"],
941+
"tag" : ["boolean_coercion", "float_truncation", "trailing_chars"]
942+
},
943+
tags: [ "$tag:L" ]
944+
}
945+
])
946+
operation InvertNumber {
947+
input: InvertNumberInput
948+
}
949+
950+
structure InvertNumberInput {
951+
@httpLabel
952+
@required
953+
numberValue: Long
954+
}
955+
673956
.. _CommonMark: https://spec.commonmark.org/
957+
.. _CodeWriter: https://awslabs.github.io/smithy/javadoc/1.13.1/software/amazon/smithy/utils/CodeWriter.html

smithy-protocol-test-traits/src/main/resources/META-INF/smithy/smithy.test.smithy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ structure HttpMalformedRequestTestCase {
331331
@private
332332
structure HttpMalformedRequestDefinition {
333333

334-
/// The expected serialized HTTP request method.
334+
/// The HTTP request method.
335335
@required
336336
@length(min: 1)
337337
method: String,
@@ -358,7 +358,7 @@ structure HttpMalformedRequestDefinition {
358358
/// percent-encoded, then it MUST appear percent-encoded in this list.
359359
queryParams: StringList,
360360

361-
/// Defines a map HTTP headers to include in the request
361+
/// Defines a map of HTTP headers to include in the request
362362
headers: StringMap,
363363

364364
/// The HTTP message body to include in the request

0 commit comments

Comments
 (0)