mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-31 19:02:59 +01:00
core: allow URL parameters and POST bodies to co-exist.
Node 8.14.0 prohibits HTTP headers that exceed 8 KB (source:
https://nodejs.org/en/blog/vulnerability/november-2018-security-releases/#denial-of-service-with-large-http-headers-cve-2018-12121).
This patch allows for the parameters within the body of an HTTP POST request to
be used in addition to those within the URL (and will override them).
Closes #3568.
---
Muxator 2019-10-19:
- this commit was cherry-picked from 882b93487f
- it was modified to include the necessary changes in the documentation
This commit is contained in:
parent
6d9264cf3c
commit
fc661ee13a
3 changed files with 35 additions and 6 deletions
|
@ -67,7 +67,28 @@ The current version can be queried via /api.
|
||||||
|
|
||||||
### Request Format
|
### Request Format
|
||||||
|
|
||||||
The API is accessible via HTTP. HTTP Requests are in the format /api/$APIVERSION/$FUNCTIONNAME. Parameters are transmitted via HTTP GET. $APIVERSION depends on the endpoints you want to use.
|
The API is accessible via HTTP. Starting from **1.8**, API endpoints can be invoked indifferently via GET or POST.
|
||||||
|
|
||||||
|
The URL of the HTTP request is of the form: `/api/$APIVERSION/$FUNCTIONNAME`. $APIVERSION depends on the endpoint you want to use. Depending on the verb you use (GET or POST) **parameters** can be passed differently.
|
||||||
|
|
||||||
|
When invoking via GET (mandatory until **1.7.5** included), parameters must be included in the query string (example: `/api/$APIVERSION/$FUNCTIONNAME?apikey=<APIKEY>¶m1=value1`). Please note that starting with nodejs 8.14+ the total size of HTTP request headers has been capped to 8192 bytes. This limits the quantity of data that can be sent in an API request.
|
||||||
|
|
||||||
|
Starting from Etherpad **1.8** it is also possible to invoke the HTTP API via POST. In this case, querystring parameters will still be accepted, but **any parameter with the same name sent via POST will take precedence**. If you need to send large chunks of text (for example, for `setText()`) it is advisable to invoke via POST.
|
||||||
|
|
||||||
|
Example with cURL using GET (toy example, no encoding):
|
||||||
|
```
|
||||||
|
curl "http://pad.domain/api/1/setText?apikey=secret&padID=padname&text=this_text_will_NOT_be_encoded_by_curl_use_next_example"
|
||||||
|
```
|
||||||
|
|
||||||
|
Example with cURL using GET (better example, encodes text):
|
||||||
|
```
|
||||||
|
curl "http://pad.domain/api/1/setText?apikey=secret&padID=padname" --get --data-urlencode "text=Text sent via GET with proper encoding. For big documents, please use POST"
|
||||||
|
```
|
||||||
|
|
||||||
|
Example with cURL using POST:
|
||||||
|
```
|
||||||
|
curl "http://pad.domain/api/1/setText?apikey=secret&padID=padname" --data-urlencode "text=Text sent via POST with proper encoding. For big texts (>8 KB), use this method"
|
||||||
|
```
|
||||||
|
|
||||||
### Response Format
|
### Response Format
|
||||||
Responses are valid JSON in the following format:
|
Responses are valid JSON in the following format:
|
||||||
|
@ -278,7 +299,9 @@ returns the text of a pad
|
||||||
#### setText(padID, text)
|
#### setText(padID, text)
|
||||||
* API >= 1
|
* API >= 1
|
||||||
|
|
||||||
sets the text of a pad
|
Sets the text of a pad.
|
||||||
|
|
||||||
|
If your text is long (>8 KB), please invoke via POST and include `text` parameter in the body of the request, not in the URL (since Etherpad **1.8**).
|
||||||
|
|
||||||
*Example returns:*
|
*Example returns:*
|
||||||
* `{code: 0, message:"ok", data: null}`
|
* `{code: 0, message:"ok", data: null}`
|
||||||
|
@ -288,7 +311,9 @@ sets the text of a pad
|
||||||
#### appendText(padID, text)
|
#### appendText(padID, text)
|
||||||
* API >= 1.2.13
|
* API >= 1.2.13
|
||||||
|
|
||||||
appends text to a pad
|
Appends text to a pad.
|
||||||
|
|
||||||
|
If your text is long (>8 KB), please invoke via POST and include `text` parameter in the body of the request, not in the URL (since Etherpad **1.8**).
|
||||||
|
|
||||||
*Example returns:*
|
*Example returns:*
|
||||||
* `{code: 0, message:"ok", data: null}`
|
* `{code: 0, message:"ok", data: null}`
|
||||||
|
@ -309,6 +334,8 @@ returns the text of a pad formatted as HTML
|
||||||
|
|
||||||
sets the text of a pad based on HTML, HTML must be well-formed. Malformed HTML will send a warning to the API log.
|
sets the text of a pad based on HTML, HTML must be well-formed. Malformed HTML will send a warning to the API log.
|
||||||
|
|
||||||
|
If `html` is long (>8 KB), please invoke via POST and include `html` parameter in the body of the request, not in the URL (since Etherpad **1.8**).
|
||||||
|
|
||||||
*Example returns:*
|
*Example returns:*
|
||||||
* `{code: 0, message:"ok", data: null}`
|
* `{code: 0, message:"ok", data: null}`
|
||||||
* `{code: 1, message:"padID does not exist", data: null}`
|
* `{code: 1, message:"padID does not exist", data: null}`
|
||||||
|
|
|
@ -40,7 +40,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
//This is a api POST call, collect all post informations and pass it to the apiHandler
|
//This is a api POST call, collect all post informations and pass it to the apiHandler
|
||||||
args.app.post('/api/:version/:func', function(req, res) {
|
args.app.post('/api/:version/:func', function(req, res) {
|
||||||
new formidable.IncomingForm().parse(req, function (err, fields, files) {
|
new formidable.IncomingForm().parse(req, function (err, fields, files) {
|
||||||
apiCaller(req, res, fields)
|
apiCaller(req, res, Object.assign(req.query, fields))
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -387,7 +387,8 @@ describe('createPad', function(){
|
||||||
|
|
||||||
describe('setText', function(){
|
describe('setText', function(){
|
||||||
it('Sets text on a pad Id', function(done) {
|
it('Sets text on a pad Id', function(done) {
|
||||||
api.get(endPoint('setText')+"&padID="+testPadId+"&text="+text)
|
api.post(endPoint('setText')+"&padID="+testPadId)
|
||||||
|
.send({text: text})
|
||||||
.expect(function(res){
|
.expect(function(res){
|
||||||
if(res.body.code !== 0) throw new Error("Pad Set Text failed")
|
if(res.body.code !== 0) throw new Error("Pad Set Text failed")
|
||||||
})
|
})
|
||||||
|
@ -410,7 +411,8 @@ describe('getText', function(){
|
||||||
|
|
||||||
describe('setText', function(){
|
describe('setText', function(){
|
||||||
it('Sets text on a pad Id including an explicit newline', function(done) {
|
it('Sets text on a pad Id including an explicit newline', function(done) {
|
||||||
api.get(endPoint('setText')+"&padID="+testPadId+"&text="+text+'%0A')
|
api.post(endPoint('setText')+"&padID="+testPadId)
|
||||||
|
.send({text: text+'\n'})
|
||||||
.expect(function(res){
|
.expect(function(res){
|
||||||
if(res.body.code !== 0) throw new Error("Pad Set Text failed")
|
if(res.body.code !== 0) throw new Error("Pad Set Text failed")
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue