skip to Main Content

I can’t make curl to work with "request_header" array in bash.

When I pass an "${request_header[@]}" array into curl command line, it will not work as expected.

But if I hard code the "-H" one by one in the curl command line, it works!

Here is the code for testing:

#!/bin/bash

send_example_by_array() {
    local -a request_header=()
    
    request_header[0]="-H"
    request_header[1]=""Accept: */*""
    
    request_header[2]="-H"
    request_header[3]=""Accept-Language: en-US,en;q=0.5""
    
    curl "${request_header[@]}" --verbose --silent --location "https://www.example.com"
}

send_example_by_array

send_example_by_hard_code_headers_in_command_line_one_by_one() {
    curl -H "Accept: */*" -H "Accept-Language: en-US,en;q=0.5" --verbose --silent --location "https://www.example.com"
}

send_example_by_hard_code_headers_in_command_line_one_by_one

Here is the output of send_example_by_array:

As you can see, the "–verbose" print the "double" accept: / headers and output will not return the HTML page content at all.

> Host: www.example.com
> user-agent: curl/7.81.0
> accept: */*
> "accept: */*"
> "accept-language: en-US,en;q=0.5"
> 
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)
* stopped the pause stream!
* Connection #0 to host www.example.com left intact

Here is the output of send_example_by_hard_code_headers_in_command_line_one_by_one:

As you can see, the "–verbose" print the only one "accept: /" header in this case, and it will return the correct HTML page.

> GET / HTTP/2
> Host: www.example.com
> user-agent: curl/7.81.0
> accept: */*
> accept-language: en-US,en;q=0.5
> 
...
< content-length: 1256
< 
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
...
</body>
</html>

The problem is, the request_header is dynamic and it may grow dynamically and it can’t be hard coded one by one.

What’s problem when passing "${request_header[@]}" to curl command line? Why not working? and How to fix?

2

Answers


  1. It’s simple! instead of keeping the -H flag and header value separate, store them as one string element in the request_header array, each element will have the flag and value together,so when you pass ${request_header[@]} to the curl command, it will treat each element as a separate argument, including the flag and value together!

    send_example_by_array() {
        local -a request_header=()
        
        request_header[0]="-H "Accept: */*""
        request_header[1]="-H "Accept-Language: en-US,en;q=0.5""
        
        curl "${request_header[@]}" --verbose --silent --location "https://www.example.com"
    }
    
    Login or Signup to reply.
  2. "Accept: ..." is not a valid HTML header. Get rid of the double quotes surrounding it:

    send_example_by_array() {
        local -a request_header=(
            -H 'Accept: */*'
            -H 'Accept-Language: en-US,en;q=0.5'
        )
        curl "${request_header[@]}" --verbose --silent --location "https://www.example.com"
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search