GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie parse ich HTTP-Header mit Bash?

Vollständiger bash Lösung. Demonstrieren Sie, wie Sie andere Header einfach parsen können, ohne dass awk erforderlich ist :

shopt -s extglob # Required to trim whitespace; see below

while IFS=':' read key value; do
    # trim whitespace in "value"
    value=${value##+([[:space:]])}; value=${value%%+([[:space:]])}

    case "$key" in
        Server) SERVER="$value"
                ;;
        Content-Type) CT="$value"
                ;;
        HTTP*) read PROTO STATUS MSG <<< "$key{$value:+:$value}"
                ;;
     esac
done < <(curl -sI http://www.google.com)
echo $STATUS
echo $SERVER
echo $CT

Produzieren:

302
GFE/2.0
text/html; charset=UTF-8

Gemäß RFC-2616 werden HTTP-Header wie in "Standard for the Format of ARPA Internet Text Messages" beschrieben modelliert (RFC822), in dem Abschnitt 3.1.2 eindeutig angegeben ist:

Der Feldname muss aus druckbaren ASCII-Zeichen bestehen (d. h. Zeichen mit Werten zwischen 33. und 126. Dezimal, außer Doppelpunkt). Der Feldkörper kann aus beliebigen ASCII-Zeichen bestehen, außer CR oder LF. (Während CR und/oder LF im eigentlichen Text vorhanden sein können, werden sie durch die Aktion des Aufklappens des Felds entfernt.)

Also das obige Skript sollte jeden RFC-[2]822-konformen Header abfangen mit der bemerkenswerten Ausnahme gefalteter Header .


Wenn Sie mehr als ein paar Header extrahieren möchten, können Sie alle Header in ein assoziatives Bash-Array packen. Hier ist eine einfache Funktion, die davon ausgeht, dass ein bestimmter Header nur einmal vorkommt. (Verwenden Sie es nicht für Set-Cookie; siehe unten.)

# Call this as: headers ARRAY URL
headers () {
  {
    # (Re)define the specified variable as an associative array.
    unset $1;
    declare -gA $1;
    local line rest

    # Get the first line, assuming HTTP/1.0 or above. Note that these fields
    # have Capitalized names.
    IFS=$' \t\n\r' read $1[Proto] $1[Status] rest
    # Drop the CR from the message, if there was one.
    declare -gA $1[Message]="${rest%$'\r'}"
    # Now read the rest of the headers. 
    while true; do
      # Get rid of the trailing CR if there is one.
      IFS=$'\r' read line rest;
      # Stop when we hit an empty line
      if [[ -z $line ]]; then break; fi
      # Make sure it looks like a header
      # This regex also strips leading and trailing spaces from the value
      if [[ $line =~ ^([[:alnum:]_-]+):\ *(( *[^ ]+)*)\ *$ ]]; then
        # Force the header to lower case, since headers are case-insensitive,
        # and store it into the array
        declare -gA $1[${BASH_REMATCH[1],,}]="${BASH_REMATCH[2]}"
      else
        printf "Ignoring non-header line: %q\n" "$line" >> /dev/stderr
      fi
    done
  } < <(curl -Is "$2")
}

Beispiel:

$ headers so http://stackoverflow.com/
$ for h in ${!so[@]}; do printf "%s=%s\n" $h "${so[$h]}"; done | sort
Message=OK
Proto=HTTP/1.1
Status=200
cache-control=public, no-cache="Set-Cookie", max-age=43
content-length=224904
content-type=text/html; charset=utf-8
date=Fri, 25 Jul 2014 17:35:16 GMT
expires=Fri, 25 Jul 2014 17:36:00 GMT
last-modified=Fri, 25 Jul 2014 17:35:00 GMT
set-cookie=prov=205fd7f3-10d4-4197-b03a-252b60df7653; domain=.stackoverflow.com; expires=Fri, 01-Jan-2055 00:00:00 GMT; path=/; HttpOnly
vary=*
x-frame-options=SAMEORIGIN

Beachten Sie, dass die SO-Antwort in Set-Cookie ein oder mehrere Cookies enthält Header, aber wir können nur den letzten sehen, weil das naive Skript Einträge mit demselben Header-Namen überschreibt. (Zufälligerweise gab es nur einen, aber das können wir nicht wissen.) Während es möglich wäre, das Skript auf den Sonderfall Set-Cookie zu erweitern , wäre ein besserer Ansatz wahrscheinlich, eine Cookie-Jar-Datei bereitzustellen und den -b zu verwenden und -c curl-Optionen, um es zu pflegen.


Linux
  1. Wie schreibe ich eine Schleife in Bash?

  2. Wie schreibe ich mit Bash Integer in eine Binärdatei?

  3. Wie kopiere ich Verzeichnisse mit install in bash in ein Verzeichnis?

  4. Wie füge ich einen Crontab-Job mit einem Bash-Skript zu Crontab hinzu?

  5. Wie listet man Ordner mit Bash-Befehlen auf?

So zeigen Sie GUI-Dialoge in Bash-Skripten mit Zenity an

So ändern Sie den GNOME-Hintergrund automatisch in Intervallen mit BASH

Bash-Skripting – Analysieren Sie Argumente in Bash-Skripten mithilfe von getopts

So analysieren Sie CSV-Dateien in Bash-Skripten unter Linux

So führen Sie ein Bash-Skript aus

So erstellen Sie einen HTTP-Proxy mit Squid unter CentOS 8