0

I am using Azure function apps with C# (or NodeJS). How to write a http post request to achieve below task?

  1. Http triger function app should send an HTTP request to a different server to get some data.
  2. Read the incoming response and send back by the http trigger source as a JSON file.

I am new to Azure function and your support would be greatly helpful.

For example

URL: https://postman-echo.com/post

HTTP's headers:

Accept: */*
Accept-Encoding: gzip, deflate, br
Connection: Keep-Alive
Content-Length: 1330
Content-Type: multipart/form-data;boundary=XXXXabcXXXX
Keep-Alive: timeout=30000
Transfer-Encoding: chunked

HTTP Body:

--XXXXabcXXXX
Content-Disposition: form-data; name="RequestData"
Content-Type: application/JSON; charset=utf-8
Content-Transfer-Encoding: 8bit

{
    "cmdDict":
        {
        "application":"b",
        "application_session_id":"cd"
        },
    "appId": "123",
    "uId":"345645"
}
--XXXXabcXXXX
Content-Disposition : form-data; name="Parameter"; paramName="REQUEST_INFO"
Content-Type: application/json; charset=utf-8
Content-Transfer-Encoding: 8bit

{
"abc":
  {"x":"default",
   "y":[],
   "message":"HELLO WORLD"
  },
"D":1
}
--XXXXabcXXXX--

2 Answers 2

2

Here's how you can do the multipart/form-data request with Node.js in Azure Functions.

The only dependency you need to install is form-data from npm.

const https = require('https')
const FormData = require('form-data')

const host = 'postman-echo.com'
const path = '/post'
const method = 'POST'
const requestHeaders = {
  Accept: '*/*',
  // add headers here as necessary
}
const parts = [
  {
    name: 'RequestData',
    data: {
      cmdDict: {
        application: 'b',
        application_session_id: 'cd',
      },
      appId: '123',
      uId: '345645',
    },
    contentType: 'application/json; charset=utf-8',
  },
  {
    name: 'Parameter',
    data: {
      abc: { x: 'default', y: [], message: 'HELLO WORLD' },
      D: 1,
    },
    contentType: 'application/json; charset=utf-8',
  },
]

async function fetchFromOrigin() {
  return new Promise((resolve, reject) => {
    const form = new FormData()

    parts.forEach((part) =>
      form.append(part.name, JSON.stringify(part.data), {
        contentType: part.contentType,
      }),
    )

    const options = {
      host,
      path,
      method,
      headers: Object.assign({}, requestHeaders, form.getHeaders()),
    }

    const req = https.request(options, (res) => {
      if (res.statusCode < 200 || res.statusCode > 299) {
        return reject(new Error(`HTTP status code ${res.statusCode}`))
      }

      const body = []
      res.on('data', (chunk) => body.push(chunk))
      res.on('end', () => {
        const resString = Buffer.concat(body).toString()
        resolve(resString)
      })
    })

    req.on('error', (err) => reject(new Error(err.message)))
    form.pipe(req)
  })
}

module.exports = async function (context, req) {
  const res = await fetchFromOrigin()

  context.res = {
    body: res,
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Amazing! It worked like a charm. I just had to tweak name: name='Parameter; paramName=REQUEST_INFO' because there is no paramName in the library. Thank you so much!
1

Please refer to this code:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Net.Http;
using System.Net.Http.Headers;
using System;

namespace FunctionMultipart
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            HttpClient _httpClient = new HttpClient();

            string URL = "https://postman-echo.com/post";
            using (var multiPartStream = new MultipartFormDataContent("XXXXabcXXXX"))
            {
                StringContent jsonPart1 = new StringContent("{\"cmdDict\": {\"application\":\"b\",\"application_session_id\":\"cd\"},\"appId\": \"123\",\"uId\":\"345645\"}");
                jsonPart1.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
                jsonPart1.Headers.ContentType = new MediaTypeHeaderValue("application/json");

                StringContent jsonPart2 = new StringContent("{\"abc\":{\"x\":\"default\",\"y\":[],\"message\":\"HELLO WORLD\"},\"D\":1}");
                jsonPart2.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
                jsonPart2.Headers.ContentType = new MediaTypeHeaderValue("application/json");

                multiPartStream.Add(jsonPart1, "RequestData");
                multiPartStream.Add(jsonPart2, "Parameter");
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, URL);
                request.Content = multiPartStream;
                //"application/json" - content type
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
                request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
                request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("br"));
                request.Headers.Connection.Add("Keep-Alive");
                //request.Headers.Add("Content-Length", "1330");
                //request.Headers.Add("Content-Type", "multipart/form-data;boundary=XXXXabcXXXX");

                HttpCompletionOption option = HttpCompletionOption.ResponseContentRead;
                System.Net.ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true);
                
                using (HttpResponseMessage response = _httpClient.SendAsync(request, option).Result)
                {
                    if (response.IsSuccessStatusCode)
                    {
                        String result = response.Content.ReadAsStringAsync().Result;
                        //var deserializedObject = JsonConvert.DeserializeObject<T>(response.Content.ReadAsStringAsync().Result);
                        //return deserializedObject.ToString();
                        log.LogInformation(result);
                    }
                }

            }

            return new OkObjectResult("ok");
        }
    }
}

1 Comment

Hey thank you so much for your reply. This is great! However, when I used webhook.site to listen to my request, I see that body of the message jsonPart1 and jsonPart2 is no in the message body. Do you know what may be missing?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.