gerardbos/h2clientserver

PUT request body

Closed this issue · 3 comments

Hello @gerardbos

I am using your h2 client library. The GET/PUT requests works perfectly fine.
As next step, I tried to send some data in PUT body but not receiving any data(body) at server.

Can you please help with this?

Modified the code as below for testing.

h2client.h

#define h2client_request_initialize()	{ \
....
....
	.requestbody.method = H2_HANDLEBODY_BUFFER, \
        .requestbody.body = "Hello", \
	.requestbody.size = 5, \
	.requestbody.content_type = "application/text", \
....
....
}

h2client.c

static ssize_t handle_request_data(nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data)
{
...
...
	switch(handle->current_request->original_request->requestbody.method){
		case H2_HANDLEBODY_BUFFER:
			{
				struct h2client_requestbody * r = &handle->current_request->original_request->requestbody;
				copied_bytes = min(r->size, length);

				memcpy(buf, &(r->body[r->written]), copied_bytes);
				r->written += copied_bytes;

				finished = r->written >= r->size;
                
// reeving these logs
                printf("[H2_HANDLEBODY_BUFFER] %.*s\n", copied_bytes, &(r->body[r->written - copied_bytes]));

			}

...
...
...

I am using a simple local node.js server to test.

const port = 4000
const spdy = require('spdy')
const express = require('express')
const path = require('path')
const fs = require('fs')
var bodyParser = require('body-parser');
var count = 0;

const app = express()

app.use(bodyParser.json());

app.use('*', function(req,res,next){
    count = count+1;
    console.log('\n\nCount: '+count);
    console.log(req.method+" "+req.originalUrl);
    console.log('params: ');
    console.log(req.params);
    console.log('headers: ');
    console.log(req.headers);
    console.log("body:");
    console.log(req.body);

    next();
})

app.put('*', (req, res) =>{
    res.status(200)
    res.json({message: 'ok', request: 'put'})
})

app.get('*', (req, res) =>{
    res.status(200)
    res.json({message: 'ok', request: 'get'})
})

const options ={
key: fs.readFileSync(__dirname + '/cert/server.key'),
cert:  fs.readFileSync(__dirname + '/cert/server.crt')
}

var server = spdy.createServer(options, app)

server.listen(port, (error) =>{
    if (error) {
        console.error(error)
        return process.exit(1)
    }
    else {
        console.log('Listening on port: ' + port + '.')
    }
})

function endApp() {
    process.exit();
} 

Note: Observed same behavior with esp-idf example https://github.com/espressif/esp-idf/tree/v3.1/examples/protocols/http2_request

To test the client, I use https://putsreq.com where I implemented an echo server (have a look at https://putsreq.com/4SqPvr1r0u4WjkSXxiup/inspect to see the endoint used in the example below).

The example transfers the request_data to the server and compares the result. If the response is equal to the contents of request_data "Echo matches" is printed. Otherwise "Echo does not match" is printed.

For me this example prints "Echo matches", so I think you have a problem with your nodejs server. Can it be that the body-parser you're using only returns a body when the input is valid json?

// required buffers and storage
char * url = "https://putsreq.com/4SqPvr1r0u4WjkSXxiup";
char request_data[] = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
char buffer[2048];

struct h2client_request r2 = h2client_request_initialize();
r2.url = url;
r2.method = H2_PUT;

r2.responsebody.method = H2_HANDLEBODY_BUFFER;
r2.responsebody.buffer = buffer;
r2.responsebody.buffer_size = sizeof(buffer);

r2.requestbody.method = H2_HANDLEBODY_BUFFER;
r2.requestbody.body = request_data;
r2.requestbody.size = sizeof(request_data) - 1;

if(h2client_do_request(&r2)){
        if(memcmp(request_data, buffer, strlen(request_data)) == 0){ 
                log(INFO, TAG, "Echo matches");
        }else{
                log(ERROR, TAG, "Echo does not match");
                log(INFO, TAG, "is: %s, should be: %s", buffer, request_data);
        }   
}else{
        log(ERROR, TAG, "Error in performing request r2");
}   

Thanks. I will have a look at it later in the day.

Yup. @gerardbos you were right. Its body parser issue. Read chunk data and its working, Thanks for pointing out.