[SOLVED] How to make this bash script clean and less repetitive?

Issue

#declaring function for GET request
api_get() {
  status=$(curl -o /dev/null -s -w "%{http_code}\n" -H "Authorization: token 123abc" "$1")

#check for condition
  if [ "$status" = 200 ]; then
    echo "Running successfully! $2 Status code: $status"
  else
    echo "Error! $2 Status code: $status"
  fi
}

#running the function for each URL
api_get https://cms.abc.co/api/method/contentready_edu_cms.api.api_1 "api_1"
api_get https://cms.abc.co/api/method/contentready_edu_cms.api.api_2 "api_2"
api_get https://cms.abc.co/api/method/contentready_edu_cms.api.api_3 "api_3"


#declaring function for POST request
api_post() {
  status=$(curl -o /dev/null -s -w "%{http_code}\n" -H "Authorization: token 123abc" -H "Content-Type: application/json" -d "$3" -X POST $1)

#check for condition
  if [ "$status" = 200 ]; then
    echo "Running successfully! $2 Status code: $status"
  else
    echo "Error! $2 Status code: $status"
  fi
}

#running the function for each URL
api_post https://cms.abc.co/api/method/contentready_edu_cms.api.api_1 "api_1" '{"some":"data1"}'
api_post https://cms.abc.co/api/method/contentready_edu_cms.api.api_2 "api_2" '{"some":"data2"}'
api_post https://cms.abc.co/api/method/contentready_edu_cms.api.api_3 "api_3" '{"some":"data3"}'

Basically first half of the code has GET request urls and second half have POST request urls with some data. I want to know how can this script be made less repetitive.

How to make 2 if statements as one? Also is it possible to combine the three lines (14-16) that are "api_get https://cms.abc.co/api/method/contentready_edu_cms.api." because the only different thing is api_1, api_2, api_3 and api names after that ("api_1", "api_2", "api_3"). If not the urls, can we at least keep them all under one api_get function?

Solution

How to make 2 if statements as one?

?? I don’t see such a thing in your code

is it possible to combine the three lines (14-16)

Yes:

api_root=https://cms.abc.co/api/method/contentready_edu_cms.api

for api in api_{1,2,3}; do
    api_get "${api_root}.${api}" "$api"
done

For the POST calls, consider an array mapping the api name to the data:

declare -A data=(
    [api_1]='{"some":"data1"}'
    [api_2]='{"some":"data2"}'
    [api_3]='{"some":"data3"}'
)

for api in "${!data[@]}"; do
    api_post "${api_root}.${api}" "$api" "${data[$api]}"
done

The two functions can be combined: just need to pass the HTTP command as a parameter.
Can do the URL construction in there too.

api() {
  local cmd=$1 api_name=$2
  local url=${api_root}.${api_name}

  local curl_opts=(
    -o /dev/null
    -s
    -w "%{http_code}\n"
    -H "Authorization: token 123abc"
  )

  case $cmd in
    GET) : ;;
    POST) 
      curl_opts+=(
        -X POST
        -H "Content-Type: application/json"
        -d "$4"
      )
      ;;
    *) echo "HTTP $cmd not implemented" >&1; return 1 ;;
  esac

  local status=$(curl "${curl_opts[@]}" "$url")

  #check for condition
  if [[ $status == 200 ]]; then
    echo "Running successfully! $api_name Status code: $status"
  else
    echo "Error! $api_name Status code: $status"
  fi
}

Then

api_root=...

api GET "api_1"

api POST "api_1" "${data[api_1]}"

Another advantage here is you don’t have to hardcode the token in two places.

Answered By – glenn jackman

Answer Checked By – Gilberto Lyons (BugsFixing Admin)

Leave a Reply

Your email address will not be published.