Skip to content

Commit b8629e8

Browse files
authored
50 fix boundary issue in multipartform data (#52)
* Fix #50 Address boundary issue * v5.5/5.6 documentation
1 parent d677874 commit b8629e8

File tree

6 files changed

+123
-25
lines changed

6 files changed

+123
-25
lines changed

docs/content-types.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
If your HTTP request has a payload and you do not specify the content type, `HttpCommand` will attempt to determine whether to use a content type of `'application/json'` or `'application/x-www-form-urlencoded'`.
2+
3+
This may be fine for interactively tinkering in the APL session. But when running `HttpCommand` under program control you should **explicitly specify the content type** for the payload by either setting `ContentType` or adding a `content-type` header.
4+
5+
The exception to this is when using `GetJSON` which is specifically intended to interact with JSON-based web services and will use a default content type of `application/json`.
6+
7+
### Special Treatment of Content Type `application/json`
8+
If you specify a content type of `'application/json'`, `HttpCommand` will automatically convert a non-JSON `Params` setting to JSON. In the rare case where `Params` is an APL character vector that happens to represent valid JSON, you should convert it yourself using `1 ⎕JSON`.
9+
10+
### Special Treatment of Content Type `multipart/form-data`
11+
Content type `multipart/form-data` is commonly used to transfer files to a server or to send multiple types of content in the request payload. If you specify a content type of `'multipart/form-data'`:
12+
13+
* `Params` must be a namespace with named elements.
14+
* Each element in `Params` consists of the data for the element optionally followed by a content type for the element.
15+
* To send a file, prefix the file name with either:
16+
* `@` to upload the file's content and its name
17+
* `<` to upload just the file's content
18+
* If you do not specify a content type for the file, `HttpCommand` will use a content type of `'text/plain'` if the extension of the file is .txt, otherwise it will use a content type of `'application/octet-stream'`.
19+
20+
In the example below:
21+
22+
* Extra newlines have been removed for compactness.
23+
* The file `/tmp/foo.txt` contains `Hello World`.
24+
* We create 4 parts to be sent with the request:
25+
* a simple string
26+
* a named file - both the content and file name will be sent
27+
* an unnamed file - only the content will be sent
28+
* a JSON array (with content type 'application/json')
29+
```
30+
h←HttpCommand.New 'post' 'someurl.com'
31+
p←⎕NS '' ⍝ create a namespace
32+
p.string←'/tmp/foo.txt' ⍝ just a value
33+
p.namedfile←'@/tmp/foo.txt' ⍝ @ = include the file name
34+
p.unnamedfile←'</tmp/foo.txt' ⍝ < = do not include the file name
35+
p.json←'[1,2,3]' 'application/json' ⍝ value and content type
36+
h.Params←p ⍝ assign the request Params
37+
h.ContentType←'multipart/form-data' ⍝
38+
h.Show
39+
POST / HTTP/1.1
40+
Host: someurl.com
41+
User-Agent: Dyalog-HttpCommand/5.6.0
42+
Accept: */*
43+
Accept-Encoding: gzip, deflate
44+
Content-Type: multipart/form-data; boundary=rgt7DIuxBqLFsveaLM0fBcR7gdvahhUfbtmuQ9UMEZvv9kDVrd
45+
Content-Length: 631
46+
47+
--rgt7DIuxBqLFsveaLM0fBcR7gdvahhUfbtmuQ9UMEZvv9kDVrd
48+
Content-Disposition: form-data; name="json"
49+
Content-Type: application/json
50+
[1,2,3]
51+
52+
--rgt7DIuxBqLFsveaLM0fBcR7gdvahhUfbtmuQ9UMEZvv9kDVrd
53+
Content-Disposition: form-data; name="namedfile"; filename="foo.txt"
54+
Content-Type: text/plain
55+
Hello World
56+
57+
--rgt7DIuxBqLFsveaLM0fBcR7gdvahhUfbtmuQ9UMEZvv9kDVrd
58+
Content-Disposition: form-data; name="string"
59+
/tmp/foo.txt
60+
61+
--rgt7DIuxBqLFsveaLM0fBcR7gdvahhUfbtmuQ9UMEZvv9kDVrd
62+
Content-Disposition: form-data; name="unnamedfile"
63+
Content-Type: text/plain
64+
Hello World
65+
66+
--rgt7DIuxBqLFsveaLM0fBcR7gdvahhUfbtmuQ9UMEZvv9kDVrd--
67+
```

docs/css/main.css

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,26 @@ pre + pre , hr + pre {
5353
}
5454
pre + pre > code, hr + pre > code {
5555
padding-top: 0.2em!important;
56+
}
57+
58+
/* make admonition styling a la Dyalog */
59+
.md-typeset .admonition,
60+
.md-typeset details {
61+
border-color: #ED7F00 !important;
62+
box-shadow: #ED7F00 !important;
63+
}
64+
65+
.md-typeset .admonition-title {
66+
background-color: #F3AD5b !important;
67+
}
68+
69+
.md-typeset .admonition-title:before,
70+
.md-typeset summary:before{
71+
background-color: #F8F8F8 !important;
72+
}
73+
74+
.md-typeset pre > code {
75+
overflow: scroll !important;
76+
scrollbar-color: black;
77+
scrollbar-width: thin;
5678
}

docs/index.md

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,36 @@
1+
`HttpCommand` is a utility is designed to make it easy for the APL user to send requests to and receive responses from HTTP servers like web servers and web services.
12

2-
__Note__: While `HttpCommand` itself is `⎕IO` and `⎕ML` insensitive, the examples in this documentation assume an environment of `(⎕IO ⎕ML)←1`.
3+
!!! note
4+
While `HttpCommand` itself is `⎕IO` and `⎕ML` insensitive, the examples in this documentation assume an environment of `(⎕IO ⎕ML)←1`.
35

46
## Loading `HttpCommand`
5-
`HttpCommand` is a utility is designed to make it easy for the APL user to send requests to and receive responses from HTTP servers like web servers and web services. `HttpCommand` is included with Dyalog APL as a loadable utility. To bring it into your workspace, simply do:
7+
`HttpCommand` is included with your Dyalog APL installation. To bring it into your workspace:
8+
9+
### Dyalog APL Version 19.0 and later
610
```APL
7-
]Load HttpCommand
11+
]import {ns} HttpCommand
812
```
913
or, under program control, do:
1014
```APL
11-
⎕SE.SALT.Load 'HttpCommand'
15+
⎕SE.Link.Import {ns} 'HttpCommand'
1216
```
13-
Beginning with Dyalog v18.2, you can also use the `]get` user command:
17+
where `{ns}` is an optional namespace name or reference.
18+
19+
### Dyalog APL versions before 19.0
1420
```APL
15-
]Get HttpCommand
21+
]load HttpCommand {-target=ns}
1622
```
23+
or, under program control, do:
24+
```APL
25+
⎕SE.SALT.Load 'HttpCommand {-target=ns}'
26+
```
27+
`{-target=ns}` optionally specifies the namespace in which to load `HttpCommand`. `ns` is the namespace name.
28+
1729

18-
## Upgrading to `HttpCommand` Version 5
19-
This documentation describes version 5 of `HttpCommand`. Dyalog versions 18.2 and 18.0 have earlier versions of `HttpCommand` pre-installed. To upgrade your in-workspace copy of `HttpCommand` to version 5, you may have to run [`HttpCommand.Upgrade`](./misc-methods.md#upgrade) once or twice depending on how recent your Dyalog installation is.
30+
## Upgrading to the Latest `HttpCommand`
31+
This documentation describes the latest version of `HttpCommand`, which may be more recent than the version of `HttpCommand` that came pre-installed with your Dyalog APL. Use [`HttpCommand.Upgrade`](./misc-methods.md#upgrade) upgrade your in-workspace copy of `HttpCommand`. Note that this only upgrades your in-workspace copy of `HttpCommand` and does not overwrite the version included in your Dyalog installation.
2032

21-
If `HttpCommand.Version` reports a version earlier than 4.0.14, `HttpCommand.Upgrade` will upgrade to the latest version 4. Then running `HttpCommand.Upgrade` once more will upgrade to version 5.
33+
If `HttpCommand.Version` reports a version earlier than 4.0.14, `HttpCommand.Upgrade` will need to be run twice to upgrade to the latest version.
2234

2335
`HttpCommand.Upgrade` does not work with Classic interpreters. See [`Upgrade`](./misc-methods.md#upgrade) for more information.
2436

@@ -33,9 +45,12 @@ For example, `HttpCommand` version 3.4 may be found in Dyalog version 18.0.
3345
HttpCommand.Version ⍝ verify that we upgraded to v4.0.14
3446
HttpCommand 4.0.14 2022-09-04
3547
HttpCommand.Upgrade ⍝ now upgrade to v5
36-
0 Upgraded to HttpCommand 5.0.7 2022-08-27 from HttpCommand 4.0.14 2022-09-04
48+
0 Upgraded to HttpCommand 5.6.0 2024-03-17 from HttpCommand 4.0.14 2022-09-04
3749
```
3850

51+
!!! note
52+
When deploying `HttpCommand` as a part of your application, you should save a copy with your application to ensure you know precisely what version of `HttpCommand` is being used. You don't want to dynamically load or upgrade `HttpCommand` in your application.
53+
3954
## `HttpCommand` is Available as a Tatin Package
4055
[Tatin](https://tatin.dev) is a package manager for APL-based packages. `HttpCommand` is available as a Tatin package. If you have the Tatin client installed, you can load `HttpCommand` using:
4156
```APL
@@ -44,7 +59,7 @@ For example, `HttpCommand` version 3.4 may be found in Dyalog version 18.0.
4459
The Tatin client will be included in your Dyalog installation beginning with Dyalog version 19.0. For earlier versions of Dyalog, refer to the [Tatin website](https://tatin.dev) for instructions on installing the Tatin client.
4560

4661
!!! warning "Load Once, Use Often"
47-
It is **strongly recommended** that you save your own copy of `HttpCommand` in your application rather than dynamically loading or upgrading it at runtime. In particular, it is bad practice to repeated load `HttpCommand` as this may cause Conga to reinitialize each time `HttpCommand` is loaded and may interfere with other components of your application that also use Conga. If `HttpCommand` is being used within your application (as opposed to ad hoc usage in your APL session) it is recommended that all Conga-using components refer to the same Conga namespace:
62+
It is **strongly recommended** that you save your own copy of `HttpCommand` in your application rather than dynamically loading or upgrading it at runtime. In particular, it is bad practice to repeated load `HttpCommand` as this may cause Conga to reinitialize each time `HttpCommand` is loaded and may interfere with other components of your application that also use Conga. If `HttpCommand` is being used within your application (as opposed to ad hoc usage in your APL session) it is recommended that all Conga-using components refer to the same Conga namespace. See [HttpCommand and Conga](./conga.md)
4863

4964
## Typical Usage Patterns
5065

docs/release-notes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## Version 5.6
2+
* Added support for content type "multipart/form-data". See [Content Types](./userguide.md#content-types).
13
## Version 5.5
24
* Added configuration setting [`Secret`](./operational-settings.md#secret) which will suppress the display of credentials in the authorization header. This is primarily so that one can demo using authenticated requests without having their credentials displayed in the session.
35
* Added ability for HTTP header names and values to reference environment variables by enclosing the environment variable name in % (e.g. `%MyPassword%`). This provides additional security by reducing the need to store sensitive or variable information inline. This is particularly useful when setting [`Auth`](./request-settings.md#auth).

docs/userguide.md

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ Typical use of `HttpCommand` might follow this pattern.
2525
```
2626
resp ← HttpCommand.Get 'some-url'
2727
:If resp.IsOK ⍝ use the IsOK function from the result namespace
28-
⍝ code to handle bad request
29-
:Else
3028
⍝ code to process the response
29+
:Else
30+
⍝ code to handle bad request
3131
:EndIf
3232
```
3333

34-
If you expect to make several `HttpCommand` calls, you may want to create an instance and then update the necessary settings and execute the `Run` method for each call. This is particularly useful when the requests are made to the same host as the connection to the host will be kept open, unless the host itself closes it.
34+
If you expect to make several `HttpCommand` calls, you may want to create an instance and then update the necessary settings and execute the `Run` method for each call. This can be useful when the requests are made to the same host as the connection to the host will be kept open, unless the host itself closes it.
3535

3636
```
3737
hc←HttpCommand.New 'get' ⍝ here we expect all requests to be HTTP GET
@@ -47,21 +47,12 @@ If you expect to make several `HttpCommand` calls, you may want to create an ins
4747
:EndIf
4848
:EndFor
4949
```
50-
## Content Types
51-
👉 If your HTTP request has a payload and you do not specify the content type, `HttpCommand` will attempt to determine whether to use a content type of `'application/json'` or `'application/x-www-form-urlencoded'`.
52-
53-
This may be fine for interactively tinkering in the APL session. But when running `HttpCommand` under program control you should **explicitly specify the content type** for the payload by either setting `ContentType` or adding a `content-type` header.
5450

55-
The exception to this is when using `GetJSON` which is specifically intended to interact with JSON-based web services and will use a default content type of `application/json`.
56-
### Special Treatment of `application/json` Content Type
57-
If you specify a content type of `'application/json'`, `HttpCommand` will automatically convert a non-JSON `Params` setting to JSON. In the rare case where `Params` is an APL character vector that is valid JSON, you should convert it yourself using `1 ⎕JSON`.
5851
## `Timeout` and Long-running Requests
5952
The default `Timeout` setting (10 seconds) is adequate for most requests. There are a couple of patterns of long running requests. `Timeout` can be set to a positive or negative number.
6053

6154
- Setting `Timeout` to a positive number means that `HttpCommand` will time out after `Timeout` seconds with a return code (`rc`) of 100. Any partial payload received will returned in `Data` element of the result.
62-
- Setting `Timeout` to a negative number means that `HttpCommand` will not time out as long as data is being received. This is useful in the case where a large payload may be received but you are uncertain of how long it will take to receive. If no data is received within a period of `Timeout` seconds, `HttpCommand` will time out with a return code (`rc`) of 100. Any partial payload received will be returned in the `Data` element of the result.
63-
64-
Using a negative `Timeout` value is useful in the case where a large payload is being received in chunks but has no benefit if the entire payload is sent in one chunk or if the host takes more than `|Timeout` seconds to begin sending its response. In that case, you'll need to set `|Timeout` to a larger value.
55+
- Setting `Timeout` to a negative number means that `HttpCommand` will not time out as long as data is being received. This is useful in the case where a large payload may be received but you are uncertain of how long it will take to receive. If no data is received within a period of `|Timeout` seconds, `HttpCommand` will time out with a return code (`rc`) of 100. Any partial payload received will be returned in the `Data` element of the result.<br/><br/> Using a negative `Timeout` value is useful in the case where a large payload is being received in chunks but has no benefit if the entire payload is sent in one chunk or if the host takes more than `|Timeout` seconds to begin sending its response. In that case, you'll need to set `|Timeout` to a larger value.
6556

6657
## Compressing Response Payload ##
6758
`HttpCommand` can accept and process response payloads that are compressed using either the gzip or deflate compression schemes. To accomplish this, you need to set the `accept-encoding` header to `'gzip, deflate'`.

mkdocs.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ site_name: HttpCommand
22
repo_url: https://github.com/dyalog/httpcommand
33
repo_name: Dyalog/HttpCommand
44
dev_addr: 127.0.0.1:22222
5-
copyright: Made with <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener"><strong>Material for MkDocs</strong></a><br/>Copyright &copy; 2015-2023 <strong><a href="https://dyalog.com" target="_blank" rel="noopener">Dyalog, LTD</a></strong>
5+
copyright: Made with <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener"><strong>Material for MkDocs</strong></a><br/>Copyright &copy; 2015-2024 <strong><a href="https://dyalog.com" target="_blank" rel="noopener">Dyalog, LTD</a></strong>
66
nav:
77
- Overview: 'index.md'
88
- Usage:
@@ -27,6 +27,7 @@ nav:
2727
- 'Response Elements': 'result-response.md' # complete
2828
- 'Messages and Return Codes': 'msgs.md' # complete
2929
- Advanced Topics:
30+
- 'Request Content Types' : 'content-types.md'
3031
- 'HttpCommand and Conga' : 'conga.md' # complete
3132
- 'Secure Communications' : 'secure.md' # complete
3233
- 'Using a Proxy Server': 'proxy.md'

0 commit comments

Comments
 (0)