存储在 bash 变量中时损坏的 png 或 jpeg 图像文件
Corrupt png or jpeg image files when stored in bash variable
我正在尝试使用 netcat 编写一个 httpserver。它不起作用我不知道为什么?当我删除“read -s GET”时,它适用于纯文本但不适用于图像,浏览器仅显示损坏图像的图标。
nc -l -k -p 80 -q 1 -e serverhttp.sh
serverhttp.sh
#!/bin/bash
index_page=index.html
error_page=Error.html
read -s GET # it doesn't work with this commond to be able to detect path.
resource=$(echo "$input" | grep -P -o '(?<=GET \/).*(?=\ )')
[ -z "$resource" ] && resource=$index_page || resource=$error_page
content_type=$(file -b --mime-type $resource)
case "$(echo "$content_type" | cut -d '/' -f2)" in
html)
output=$(cat "$resource")
;;
jpeg)
output=$(cat "$resource")
;;
png)
output=$(cat "$resource")
;;
*)
echo 'Unknown type'
esac
content_length=$(stat -c '%s' $resource)
echo -ne "HTTP 200 OK\r\n"
echo -ne "Content-Length: $content_length\r\n"
echo -ne "Content-Type: $content_type\r\n\n$output\n"
它不适用于图像文件的原因是因为这些是二进制数据,Shell 无法将二进制存储到变量中,如下所示:
output=$(cat "$resource")
也如 there are code pitfalls that would be shown to you with a code check from https://shellcheck.net/
所述
以下是处理二进制文件的方法:
#!/usr/bin/env bash
# Function to stream a binary file as HTTP body
send_body () {
printf '\r\n'
cat "" 2>/dev/null || : # Can stream binary data
printf '\r\n'
}
input=
index_page=index.html
error_page=Error.html
# Parses the request string with Bash's built-in Regex engine
[[ "$input" =~ ^GET[[:space:]]/(.*)/?[[:space:]]HTTP/1\.[01]?$ ]] || :
resource=${BASH_REMATCH[1]}
# When resource is empty, substitute the value of $index_page
resource=${resource:-$index_page}
# Capture mime type
content_type=$(file -b --mime-type "$resource")
# Set http status code depending on if resource file exist
if [ -f "$resource" ]; then
http_status='200 OK'
else
resource="$error_page"
content_type='text/html'
http_status='404 NOT FOUND'
fi
# Check supported MIME types
case "${content_type#*/}" in
html | jpeg | png) ;;
*)
printf '%s\n' 'Unknown type' >&2
resource="$error_page"
content_type='text/html'
http_status='415 UNSUPPORTED MEDIA TYPE'
;;
esac
# Capture the content_length (default to 0)
read -r content_length _ < <(wc -c "$resource" 2>/dev/null)
content_length=${content_length:-0}
# Send reply
printf 'HTTP %s\r\n' "$http_status"
printf 'Content-Length: %d\r\n' "$content_length"
printf 'Content-Type: %s\r\n' "$content_type"
send_body "$resource"
我正在尝试使用 netcat 编写一个 httpserver。它不起作用我不知道为什么?当我删除“read -s GET”时,它适用于纯文本但不适用于图像,浏览器仅显示损坏图像的图标。
nc -l -k -p 80 -q 1 -e serverhttp.sh
serverhttp.sh
#!/bin/bash
index_page=index.html
error_page=Error.html
read -s GET # it doesn't work with this commond to be able to detect path.
resource=$(echo "$input" | grep -P -o '(?<=GET \/).*(?=\ )')
[ -z "$resource" ] && resource=$index_page || resource=$error_page
content_type=$(file -b --mime-type $resource)
case "$(echo "$content_type" | cut -d '/' -f2)" in
html)
output=$(cat "$resource")
;;
jpeg)
output=$(cat "$resource")
;;
png)
output=$(cat "$resource")
;;
*)
echo 'Unknown type'
esac
content_length=$(stat -c '%s' $resource)
echo -ne "HTTP 200 OK\r\n"
echo -ne "Content-Length: $content_length\r\n"
echo -ne "Content-Type: $content_type\r\n\n$output\n"
它不适用于图像文件的原因是因为这些是二进制数据,Shell 无法将二进制存储到变量中,如下所示:
output=$(cat "$resource")
也如
以下是处理二进制文件的方法:
#!/usr/bin/env bash
# Function to stream a binary file as HTTP body
send_body () {
printf '\r\n'
cat "" 2>/dev/null || : # Can stream binary data
printf '\r\n'
}
input=
index_page=index.html
error_page=Error.html
# Parses the request string with Bash's built-in Regex engine
[[ "$input" =~ ^GET[[:space:]]/(.*)/?[[:space:]]HTTP/1\.[01]?$ ]] || :
resource=${BASH_REMATCH[1]}
# When resource is empty, substitute the value of $index_page
resource=${resource:-$index_page}
# Capture mime type
content_type=$(file -b --mime-type "$resource")
# Set http status code depending on if resource file exist
if [ -f "$resource" ]; then
http_status='200 OK'
else
resource="$error_page"
content_type='text/html'
http_status='404 NOT FOUND'
fi
# Check supported MIME types
case "${content_type#*/}" in
html | jpeg | png) ;;
*)
printf '%s\n' 'Unknown type' >&2
resource="$error_page"
content_type='text/html'
http_status='415 UNSUPPORTED MEDIA TYPE'
;;
esac
# Capture the content_length (default to 0)
read -r content_length _ < <(wc -c "$resource" 2>/dev/null)
content_length=${content_length:-0}
# Send reply
printf 'HTTP %s\r\n' "$http_status"
printf 'Content-Length: %d\r\n' "$content_length"
printf 'Content-Type: %s\r\n' "$content_type"
send_body "$resource"