{"id":627,"date":"2012-02-01T12:12:24","date_gmt":"2012-02-01T11:12:24","guid":{"rendered":"http:\/\/locallost.net\/?p=627"},"modified":"2012-02-01T12:22:58","modified_gmt":"2012-02-01T11:22:58","slug":"doing-tcphttp-with-bash","status":"publish","type":"post","link":"https:\/\/locallost.net\/?p=627","title":{"rendered":"Doing TCP\/HTTP with Bash"},"content":{"rendered":"<p>Bash have the ability to do I\/O on TCP sockets through the special file \u00ab\u00a0\/dev\/tcp\/&lt;host&gt;\/&lt;port&gt;\u00a0\u00bb.<\/p>\n<p>Here is a simple setup that demonstrate this capability by implementing a simple HTTP client.<\/p>\n<p><!--more--><\/p>\n<pre>\r\n#!\/bin\/bash\r\n\r\nif [ $# -ne 3 ]; then\r\n\techo \"Usage:\"\r\n\techo \"  $0 &lt;host&gt; &lt;port&gt; &lt;\/resource\/to\/get&gt;\"\r\n\techo \"\"\r\n\texit\r\nfi\r\n\r\nHOST=$1\r\nPORT=$2\r\nRESOURCE=$3\r\n\r\n# Connect fd#3 to the TCP socket\r\nexec 3<> \"\/dev\/tcp\/$HOST\/$PORT\"\r\n\r\n# Send request to fd 3\r\necho -n -e \"GET $RESOURCE HTTP\/1.1\\r\\n\" 1&gt;&amp;3\r\nif [ \"$PORT\" = \"80\" ]; then\r\n\techo -n -e \"Host: $HOST\\r\\n\" 1&gt;&amp;3\r\nelse\r\n\techo -n -e \"Host: $HOST:$PORT\\r\\n\" 1&gt;&amp;3\r\nfi\r\necho -n -e \"Connection: close\\r\\n\" 1&gt;&amp;3\r\necho -n -e \"\\r\\n\" 1&gt;&amp;3\r\n\r\n# Read HTTP status line from fd 3\r\nread STATUS 0&lt;&amp;3\r\nSTATUS=$(echo \"$STATUS\" | tr -d '\\r\\n')\r\necho \"Status [[[$STATUS]]]\" 1&gt;&amp;2\r\n\r\n# Read the HTTP headers from fd 3\r\nwhile read HEADER 0&lt;&amp;3; do\r\n\tHEADER=$(echo \"$HEADER\" | tr -d '\\r\\n')\r\n\tif [ \"$HEADER\" = \"\" ]; then\r\n\t\tbreak\r\n\tfi\r\n\techo \"Header [[[$HEADER]]]\" 1&gt;&amp;2\r\ndone\r\n\r\n# Only handle HTTP 200\r\nif [ \"${STATUS:9:3}\" != \"200\" ]; then\r\n\techo \"Server responded with an unexpected status code [[[$STATUS]]]\" 1&gt;&amp;2\r\n\texit\r\nfi\r\n\r\n# Print the HTTP response data\r\ncat 0&lt;&amp;3\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Bash have the ability to do I\/O on TCP sockets through the special file \u00ab\u00a0\/dev\/tcp\/&lt;host&gt;\/&lt;port&gt;\u00a0\u00bb. Here is a simple setup that demonstrate this capability by implementing a simple HTTP client.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4],"tags":[],"class_list":["post-627","post","type-post","status-publish","format-standard","hentry","category-code"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p2Bei9-a7","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/locallost.net\/index.php?rest_route=\/wp\/v2\/posts\/627","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/locallost.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/locallost.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/locallost.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/locallost.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=627"}],"version-history":[{"count":12,"href":"https:\/\/locallost.net\/index.php?rest_route=\/wp\/v2\/posts\/627\/revisions"}],"predecessor-version":[{"id":639,"href":"https:\/\/locallost.net\/index.php?rest_route=\/wp\/v2\/posts\/627\/revisions\/639"}],"wp:attachment":[{"href":"https:\/\/locallost.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=627"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/locallost.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=627"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/locallost.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=627"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}