Home > database >  How to make this bash script clean and less repetitive?
How to make this bash script clean and less repetitive?

Time:01-28

#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?

CodePudding user response:

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.

CodePudding user response:

I assume that "api_1, api_2, etc" is not always consecutive, so a simple approach is to create separated lists with the URLs and the data then pass that to the script. If you add the below section to your current script you can run it like this

bash request.sh get get_list.txt and bash request.sh post post_list.txt

method="${1}"
file="${2}"

case "${method}" in
    get|post);;
    *) exit 1;;
esac

[ ! -e "${file}" ] && exit 1;

OFS=$IFS
IFS=$'\n'
while read line; do
    api_url=$(echo ${line} | cut -d' ' -f1)
    # only required by post method, it will be empty if there is no data and ignored by your get function
    data=$(echo ${line} | cut -d' ' -f2)

    api_name=$(echo ${api_url} | awk -F'.' '{print $NF}')
    api_${method} "${api_url}" "${api_name}" "${data}"

done < ${file}
IFS=$OFS

The name is extracted from the URL, so there is no need to pass it as a parameter

get_list.txt:

https://cms.abc.co/api/method/contentready_edu_cms.api.api_1
https://cms.abc.co/api/method/contentready_edu_cms.api.api_2
https://cms.abc.co/api/method/contentready_edu_cms.api.api_3

post_list.txt:

https://cms.abc.co/api/method/contentready_edu_cms.api.api_1 '{"some":"data1"}'
https://cms.abc.co/api/method/contentready_edu_cms.api.api_2 '{"some":"data2"}'
https://cms.abc.co/api/method/contentready_edu_cms.api.api_3 '{"some":"data3"}'
  •  Tags:  
  • Related