(command.CommandList children: [ (command.ShFunction name: warn body: (command.BraceGroup children: [ (command.Sentence child: (command.Simple words: [{(echo)} {(DQ ('WARNING: ') ($ Id.VSub_At '$@'))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:38) fd: -1 arg_word: {(2)} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:40) ) ] ) ) (command.AndOr ops: [Id.Op_DPipe] children: [ (C {(Id.Lit_LBracket '[')} {(-r)} {(bashttpd.conf)} {(Id.Lit_RBracket ']')}) (command.BraceGroup children: [ (command.Simple words: [{(cat)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:60) fd: -1 arg_word: {(bashttpd.conf)} ) (redir.HereDoc op: (Token id:Id.Redir_DLess val:'<<' span_id:63) fd: -1 here_begin: {(SQ (Token id:Id.Lit_Chars val:EOF span_id:65))} here_end_span_id: 156 stdin_parts: [ ('#\n') ('# bashttpd.conf - configuration for bashttpd\n') ('#\n') ('# The behavior of bashttpd is dictated by the evaluation\n') ('# of rules specified in this configuration file. Each rule\n') ('# is evaluated until one is matched. If no rule is matched,\n') ('# bashttpd will serve a 500 Internal Server Error.\n') ('#\n') ('# The format of the rules are:\n') ('# on_uri_match REGEX command [args]\n') ('# unconditionally command [args]\n') ('#\n') ('# on_uri_match:\n') ('# On an incoming request, the URI is checked against the specified\n') ( '# (bash-supported extended) regular expression, and if encounters a match the\n' ) ('# specified command is executed with the specified arguments.\n') ('#\n') ( '# For additional flexibility, on_uri_match will also pass the results of the\n' ) ( '# regular expression match, ${BASH_REMATCH[@]} as additional arguments to the\n' ) ('# command.\n') ('#\n') ('# unconditionally:\n') ('# Always serve via the specified command. Useful for catchall rules.\n') ('#\n') ('# The following commands are available for use:\n') ('#\n') ('# serve_file FILE\n') ('# Statically serves a single file.\n') ('#\n') ('# serve_dir_with_tree DIRECTORY\n') ("# Statically serves the specified directory using 'tree'. It must be\n") ('# installed and in the PATH.\n') ('#\n') ('# serve_dir_with_ls DIRECTORY\n') ("# Statically serves the specified directory using 'ls -al'.\n") ('#\n') ('# serve_dir DIRECTORY\n') ( "# Statically serves a single directory listing. Will use 'tree' if it is\n" ) ("# installed and in the PATH, otherwise, 'ls -al'\n") ('#\n') ('# serve_dir_or_file_from DIRECTORY\n') ('# Serves either a directory listing (using serve_dir) or a file (using\n') ('# serve_file). Constructs local path by appending the specified root\n') ('# directory, and the URI portion of the client request.\n') ('#\n') ('# serve_static_string STRING\n') ('# Serves the specified static string with Content-Type text/plain.\n') ('#\n') ('# Examples of rules:\n') ('#\n') ('# on_uri_match \'^/issue$\' serve_file "/etc/issue"\n') ('#\n') ( "# When a client's requested URI matches the string '/issue', serve them the\n" ) ('# contents of /etc/issue\n') ('#\n') ("# on_uri_match 'root' serve_dir /\n") ('#\n') ("# When a client's requested URI has the word 'root' in it, serve up\n") ('# a directory listing of /\n') ('#\n') ('# DOCROOT=/var/www/html\n') ('# on_uri_match \'/(.*)\' serve_dir_or_file_from "$DOCROOT"\n') ('# When any URI request is made, attempt to serve a directory listing\n') ("# or file content based on the request URI, by mapping URI's to local\n") ('# paths relative to the specified "$DOCROOT"\n') ('#\n') ('\n') ( "unconditionally serve_static_string 'Hello, world! You can configure bashttpd by modifying bashttpd.conf.'\n" ) ('\n') ('# More about commands:\n') ('#\n') ('# It is possible to somewhat easily write your own commands. An example\n') ('# may help. The following example will serve "Hello, $x!" whenever\n') ('# a client sends a request with the URI /say_hello_to/$x:\n') ('#\n') ('# serve_hello() {\n') ('# add_response_header "Content-Type" "text/plain"\n') ('# send_response_ok_exit <<< "Hello, $2!"\n') ('# }\n') ("# on_uri_match '^/say_hello_to/(.*)$' serve_hello\n") ('#\n') ('# Like mentioned before, the contents of ${BASH_REMATCH[@]} are passed\n') ('# to your command, so its possible to use regular expression groups\n') ('# to pull out info.\n') ('#\n') ( '# With this example, when the requested URI is /say_hello_to/Josh, serve_hello\n' ) ("# is invoked with the arguments '/say_hello_to/Josh' 'Josh',\n") ('# (${BASH_REMATCH[0]} is always the full match)\n') ] ) ] ) (C {(warn)} { (DQ ( 'Created bashttpd.conf using defaults. Please review it/configure before running bashttpd again.' ) ) } ) (command.ControlFlow token: (Token id:Id.ControlFlow_Exit val:exit span_id:165) arg_word: {(1)} ) ] ) ] ) (command.ShFunction name: recv body: (command.BraceGroup children: [ (command.Sentence child: (command.Simple words: [{(echo)} {(DQ ('< ') ($ Id.VSub_At '$@'))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:185) fd: -1 arg_word: {(2)} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:187) ) ] ) ) (command.ShFunction name: send body: (command.BraceGroup children: [ (command.Sentence child: (command.Simple words: [{(echo)} {(DQ ('> ') ($ Id.VSub_At '$@'))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:204) fd: -1 arg_word: {(2)} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:206) ) (command.Sentence child: (C {(printf)} {(SQ (Token id:Id.Lit_Chars val:'%s\\r\\n' span_id:212))} {(DQ ($ Id.VSub_Star '$*'))} ) terminator: (Token id:Id.Op_Semi val:';' span_id:218) ) ] ) ) (command.AndOr ops: [Id.Op_DAmp] children: [ (command.DBracket expr: (bool_expr.Binary op_id: Id.BoolBinary_GlobEqual left: {($ Id.VSub_DollarName '$UID')} right: {(0)} ) ) (C {(warn)} {(DQ ('It is not recommended to run bashttpd as root.'))}) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:DATE) op: assign_op.Equal rhs: { (command_sub left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:243) command_list: (command.CommandList children: [(C {(date)} {(Id.Lit_Other '+') (DQ ('%a, %d %b %Y %H:%M:%S %Z'))})] ) ) } spids: [242] ) ] ) (C {(declare)} {(-a)} {(Id.Lit_VarLike 'RESPONSE_HEADERS=') (sh_array_literal left: (Token id:Id.Op_LParen val:'(' span_id:257) words: [ {(DQ ('Date: ') ($ Id.VSub_DollarName '$DATE'))} {(DQ ('Expires: ') ($ Id.VSub_DollarName '$DATE'))} {(DQ ('Server: Slash Bin Slash Bash'))} ] ) } ) (command.ShFunction name: add_response_header body: (command.BraceGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:RESPONSE_HEADERS) op: assign_op.PlusEqual rhs: { (sh_array_literal left: (Token id:Id.Op_LParen val:'(' span_id:287) words: [{(DQ ($ Id.VSub_Number '$1') (': ') ($ Id.VSub_Number '$2'))}] ) } spids: [286] ) ] ) ] ) ) (C {(declare)} {(-a)} {(Id.Lit_VarLike 'HTTP_RESPONSE=') (word_part.AssocArrayLiteral left: (Token id:Id.Op_LParen val:'(' span_id:303) pairs: [ {(200)} {(DQ (OK))} {(400)} {(DQ ('Bad Request'))} {(403)} {(DQ (Forbidden))} {(404)} {(DQ ('Not Found'))} {(405)} {(DQ ('Method Not Allowed'))} {(500)} {(DQ ('Internal Server Error'))} ] ) } ) (command.ShFunction name: send_response body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'code=') ($ Id.VSub_Number '$1')}) (C {(send)} { (DQ ('HTTP/1.0 ') ($ Id.VSub_Number '$1') (' ') (braced_var_sub token: (Token id:Id.VSub_Name val:HTTP_RESPONSE span_id:376) bracket_op: (bracket_op.ArrayIndex expr: (arith_expr.ArithWord w:{($ Id.VSub_Number '$1')}) ) ) ) } ) (command.ForEach iter_name: i iter_words: [ { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:RESPONSE_HEADERS span_id:392) bracket_op: (bracket_op.WholeArray op_id:Id.Lit_At) ) ) } ] do_arg_iter: F body: (command.DoGroup children:[(C {(send)} {(DQ ($ Id.VSub_DollarName '$i'))})]) ) (C {(send)}) (command.WhileUntil keyword: (Token id:Id.KW_While val:while span_id:416) cond: [ (command.Sentence child: (C {(read)} {(-r)} {(line)}) terminator: (Token id:Id.Op_Semi val:';' span_id:423) ) ] body: (command.DoGroup children:[(C {(send)} {(DQ ($ Id.VSub_DollarName '$line'))})]) ) ] ) ) (command.ShFunction name: send_response_ok_exit body: (command.BraceGroup children: [ (command.Sentence child: (C {(send_response)} {(200)}) terminator: (Token id:Id.Op_Semi val:';' span_id:449) ) (command.Sentence child: (command.ControlFlow token: (Token id:Id.ControlFlow_Exit val:exit span_id:451) arg_word: {(0)} ) terminator: (Token id:Id.Op_Semi val:';' span_id:454) ) ] ) ) (command.ShFunction name: fail_with body: (command.BraceGroup children: [ (command.Simple words: [{(send_response)} {(DQ ($ Id.VSub_Number '$1'))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_TLess val:'<<<' span_id:472) fd: -1 arg_word: { (DQ ($ Id.VSub_Number '$1') (' ') (braced_var_sub token: (Token id:Id.VSub_Name val:HTTP_RESPONSE span_id:478) bracket_op: (bracket_op.ArrayIndex expr: (arith_expr.ArithWord w:{($ Id.VSub_Number '$1')}) ) ) ) } ) ] ) (command.ControlFlow token: (Token id:Id.ControlFlow_Exit val:exit span_id:486) arg_word: {(1)} ) ] ) ) (command.ShFunction name: serve_file body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'file=') ($ Id.VSub_Number '$1')}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:CONTENT_TYPE) op: assign_op.Equal rhs: (word.Empty) spids: [507] ) ] ) (command.Case to_match: {(DQ ($ Id.VSub_DollarName '$file'))} arms: [ (case_arm pat_list: [ {(Id.Lit_Star '*') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\.' span_id:520) ) (css) } ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:CONTENT_TYPE) op: assign_op.Equal rhs: {(DQ (text/css))} spids: [525] ) ] ) ] spids: [519 522 531 -1] ) (case_arm pat_list: [ {(Id.Lit_Star '*') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\.' span_id:535) ) (js) } ] action: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:CONTENT_TYPE) op: assign_op.Equal rhs: {(DQ (text/javascript))} spids: [540] ) ] ) ] spids: [534 537 546 -1] ) (case_arm pat_list: [{(Id.Lit_Star '*')}] action: [ (command.Simple words: [{(read)} {(-r)} {(CONTENT_TYPE)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Less val:'<' span_id:559) fd: -1 arg_word: { (command_sub left_token: (Token id:Id.Left_ProcSubIn val:'<(' span_id:561) command_list: (command.CommandList children: [ (C {(file)} {(-b)} {(--mime-type)} {(DQ ($ Id.VSub_DollarName '$file'))} ) ] ) ) } ) ] ) ] spids: [549 550 574 -1] ) ] ) (command.Sentence child: (C {(add_response_header)} {(DQ (Content-Type))} {(DQ ($ Id.VSub_DollarName '$CONTENT_TYPE'))} ) terminator: (Token id:Id.Op_Semi val:';' span_id:590) ) (command.AndOr ops: [Id.Op_DAmp] children: [ (command.Simple words: [{(read)} {(-r)} {(CONTENT_LENGTH)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Less val:'<' span_id:600) fd: -1 arg_word: { (command_sub left_token: (Token id:Id.Left_ProcSubIn val:'<(' span_id:602) command_list: (command.CommandList children: [ (C {(stat)} {(-c) (SQ (Token id:Id.Lit_Chars val:'%s' span_id:607))} {(DQ ($ Id.VSub_DollarName '$file'))} ) ] ) ) } ) ] ) (C {(add_response_header)} {(DQ (Content-Length))} {(DQ ($ Id.VSub_DollarName '$CONTENT_LENGTH'))} ) ] ) (command.Simple words: [{(send_response_ok_exit)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Less val:'<' span_id:633) fd: -1 arg_word: {(DQ ($ Id.VSub_DollarName '$file'))} ) ] ) ] ) ) (command.ShFunction name: serve_dir_with_tree body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'dir=') (DQ ($ Id.VSub_Number '$1'))} {(tree_vers)} {(tree_opts)} {(basehref)} {(x)} ) (C {(add_response_header)} {(DQ (Content-Type))} {(DQ (text/html))}) (command.Simple words: [{(read)} {(x)} {(tree_vers)} {(x)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Less val:'<' span_id:690) fd: -1 arg_word: { (command_sub left_token: (Token id:Id.Left_ProcSubIn val:'<(' span_id:692) command_list: (command.CommandList children:[(C {(tree)} {(--version)})]) ) } ) ] ) (command.AndOr ops: [Id.Op_DAmp] children: [ (command.DBracket expr: (bool_expr.Binary op_id: Id.BoolBinary_GlobDEqual left: {($ Id.VSub_DollarName '$tree_vers')} right: {(v1.6) (Id.Lit_Other '*')} ) ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:tree_opts) op: assign_op.Equal rhs: {(DQ (--du))} spids: [712] ) ] ) ] ) (command.Simple words: [{(send_response_ok_exit)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Less val:'<' span_id:721) fd: -1 arg_word: { (command_sub left_token: (Token id:Id.Left_ProcSubIn val:'<(' span_id:725) command_list: (command.CommandList children: [ (C {(tree)} {(-H)} {(DQ ($ Id.VSub_Number '$2'))} {(-L)} {(1)} {(DQ ($ Id.VSub_DollarName '$tree_opts'))} {(-D)} {(DQ ($ Id.VSub_DollarName '$dir'))} ) ] ) ) } ) ] ) ] ) ) (command.ShFunction name: serve_dir_with_ls body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'dir=') ($ Id.VSub_Number '$1')}) (C {(add_response_header)} {(DQ (Content-Type))} {(DQ (text/plain))}) (command.Simple words: [{(send_response_ok_exit)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Less val:'<' span_id:780) fd: -1 arg_word: { (command_sub left_token: (Token id:Id.Left_ProcSubIn val:'<(' span_id:784) command_list: (command.CommandList children: [(C {(ls)} {(-la)} {(DQ ($ Id.VSub_DollarName '$dir'))})] ) ) } ) ] ) ] ) ) (command.ShFunction name: serve_dir body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'dir=') ($ Id.VSub_Number '$1')}) (command.AndOr ops: [Id.Op_DAmp] children: [ (command.Simple words: [{(which)} {(tree)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_AndGreat val:'&>' span_id:819) fd: -1 arg_word: {(/dev/null)} ) ] ) (C {(serve_dir_with_tree)} {(DQ ($ Id.VSub_At '$@'))}) ] ) (C {(serve_dir_with_ls)} {(DQ ($ Id.VSub_At '$@'))}) (C {(fail_with)} {(500)}) ] ) ) (command.ShFunction name: serve_dir_or_file_from body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'URL_PATH=') ($ Id.VSub_Number '$1') (/) ($ Id.VSub_Number '$3')} ) (C {(shift)}) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:URL_PATH) op: assign_op.Equal rhs: { (braced_var_sub token: (Token id:Id.VSub_Name val:URL_PATH span_id:874) suffix_op: (suffix_op.PatSub pat: {('[^a-zA-Z0-9_~') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\-' span_id:878) ) (word_part.EscapedLiteral token:(Token id:Id.Lit_EscapedChar val:'\\.' span_id:879)) (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\/' span_id:880) ) (']') } replace: {} replace_mode: Id.Lit_Slash ) ) } spids: [872] ) ] ) (command.AndOr ops: [Id.Op_DAmp] children: [ (command.DBracket expr: (bool_expr.Binary op_id: Id.BoolBinary_GlobDEqual left: {($ Id.VSub_DollarName '$URL_PATH')} right: {(Id.Lit_Other '*') (..) (Id.Lit_Other '*')} ) ) (C {(fail_with)} {(400)}) ] ) (command.AndOr ops: [Id.Op_DAmp] children: [ (command.DBracket expr: (bool_expr.LogicalAnd left: (bool_expr.Unary op_id: Id.BoolUnary_d child: {($ Id.VSub_DollarName '$URL_PATH')} ) right: (bool_expr.LogicalAnd left: (bool_expr.Unary op_id: Id.BoolUnary_f child: {($ Id.VSub_DollarName '$URL_PATH') (/index.html)} ) right: (bool_expr.Unary op_id: Id.BoolUnary_r child: {($ Id.VSub_DollarName '$URL_PATH') (/index.html)} ) ) ) ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:URL_PATH) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_DollarName '$URL_PATH') (/index.html))} spids: [936] ) ] ) ] ) (command.If arms: [ (if_arm cond: [ (command.Sentence child: (command.DBracket expr: (bool_expr.Unary op_id: Id.BoolUnary_f child: {($ Id.VSub_DollarName '$URL_PATH')} ) ) terminator: (Token id:Id.Op_Semi val:';' span_id:953) ) ] action: [ (command.AndOr ops: [Id.Op_DAmp Id.Op_DPipe] children: [ (command.DBracket expr: (bool_expr.Unary op_id: Id.BoolUnary_r child: {($ Id.VSub_DollarName '$URL_PATH')} ) ) (C {(serve_file)} {(DQ ($ Id.VSub_DollarName '$URL_PATH'))} {(DQ ($ Id.VSub_At '$@'))} ) (C {(fail_with)} {(403)}) ] ) ] spids: [944 955] ) (if_arm cond: [ (command.Sentence child: (command.DBracket expr: (bool_expr.Unary op_id: Id.BoolUnary_d child: {($ Id.VSub_DollarName '$URL_PATH')} ) ) terminator: (Token id:Id.Op_Semi val:';' span_id:996) ) ] action: [ (command.AndOr ops: [Id.Op_DAmp Id.Op_DPipe] children: [ (command.DBracket expr: (bool_expr.Unary op_id: Id.BoolUnary_x child: {($ Id.VSub_DollarName '$URL_PATH')} ) ) (C {(serve_dir)} {(DQ ($ Id.VSub_DollarName '$URL_PATH'))} {(DQ ($ Id.VSub_At '$@'))} ) (C {(fail_with)} {(403)}) ] ) ] spids: [987 998] ) ] ) (C {(fail_with)} {(404)}) ] ) ) (command.ShFunction name: serve_static_string body: (command.BraceGroup children: [ (C {(add_response_header)} {(DQ (Content-Type))} {(DQ (text/plain))}) (command.Simple words: [{(send_response_ok_exit)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_TLess val:'<<<' span_id:1061) fd: -1 arg_word: {(DQ ($ Id.VSub_Number '$1'))} ) ] ) ] ) ) (command.ShFunction name: on_uri_match body: (command.BraceGroup children: [ (C {(local)} {(Id.Lit_VarLike 'regex=') ($ Id.VSub_Number '$1')}) (C {(shift)}) (command.AndOr ops: [Id.Op_DAmp] children: [ (command.DBracket expr: (bool_expr.Binary op_id: Id.BoolBinary_EqualTilde left: {($ Id.VSub_DollarName '$REQUEST_URI')} right: {($ Id.VSub_DollarName '$regex')} ) ) (C {(DQ ($ Id.VSub_At '$@'))} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:BASH_REMATCH span_id:1107) bracket_op: (bracket_op.WholeArray op_id:Id.Lit_At) ) ) } ) ] ) ] ) ) (command.ShFunction name: unconditionally body: (command.BraceGroup children: [(C {(DQ ($ Id.VSub_At '$@'))} {(DQ ($ Id.VSub_DollarName '$REQUEST_URI'))})] ) ) (command.AndOr ops: [Id.Op_DPipe] children: [(C {(read)} {(-r)} {(line)}) (C {(fail_with)} {(400)})] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:line) op: assign_op.Equal rhs: { (braced_var_sub token: (Token id:Id.VSub_Name val:line span_id:1156) suffix_op: (suffix_op.Unary op_id: Id.VOp1_DPercent arg_word: { (single_quoted left: (Token id:Id.Left_SingleQuoteC val:"$'" span_id:1158) tokens: [(Token id:Id.Char_OneChar val:'\\r' span_id:1159)] ) } ) ) } spids: [1154] ) ] ) (C {(recv)} {(DQ ($ Id.VSub_DollarName '$line'))}) (command.Simple words: [{(read)} {(-r)} {(REQUEST_METHOD)} {(REQUEST_URI)} {(REQUEST_HTTP_VERSION)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_TLess val:'<<<' span_id:1180) fd: -1 arg_word: {(DQ ($ Id.VSub_DollarName '$line'))} ) ] ) (command.AndOr ops: [Id.Op_DAmp Id.Op_DAmp Id.Op_DPipe] children: [ (C {(Id.Lit_LBracket '[')} {(-n)} {(DQ ($ Id.VSub_DollarName '$REQUEST_METHOD'))} {(Id.Lit_RBracket ']')} ) (C {(Id.Lit_LBracket '[')} {(-n)} {(DQ ($ Id.VSub_DollarName '$REQUEST_URI'))} {(Id.Lit_RBracket ']')} ) (C {(Id.Lit_LBracket '[')} {(-n)} {(DQ ($ Id.VSub_DollarName '$REQUEST_HTTP_VERSION'))} {(Id.Lit_RBracket ']')} ) (C {(fail_with)} {(400)}) ] ) (command.AndOr ops: [Id.Op_DPipe] children: [ (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$REQUEST_METHOD'))} {(Id.Lit_Equals '=')} {(DQ (GET))} {(Id.Lit_RBracket ']')} ) (C {(fail_with)} {(405)}) ] ) (C {(declare)} {(-a)} {(REQUEST_HEADERS)}) (command.WhileUntil keyword: (Token id:Id.KW_While val:while span_id:1262) cond: [ (command.Sentence child: (C {(read)} {(-r)} {(line)}) terminator: (Token id:Id.Op_Semi val:';' span_id:1269) ) ] body: (command.DoGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:line) op: assign_op.Equal rhs: { (braced_var_sub token: (Token id:Id.VSub_Name val:line span_id:1276) suffix_op: (suffix_op.Unary op_id: Id.VOp1_DPercent arg_word: { (single_quoted left: (Token id:Id.Left_SingleQuoteC val:"$'" span_id:1278) tokens: [(Token id:Id.Char_OneChar val:'\\r' span_id:1279)] ) } ) ) } spids: [1274] ) ] ) (C {(recv)} {(DQ ($ Id.VSub_DollarName '$line'))}) (command.AndOr ops: [Id.Op_DAmp] children: [ (C {(Id.Lit_LBracket '[')} {(-z)} {(DQ ($ Id.VSub_DollarName '$line'))} {(Id.Lit_RBracket ']')} ) (command.ControlFlow token: (Token id:Id.ControlFlow_Break val:break span_id:1308) ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:REQUEST_HEADERS) op: assign_op.PlusEqual rhs: { (sh_array_literal left: (Token id:Id.Op_LParen val:'(' span_id:1313) words: [{(DQ ($ Id.VSub_DollarName '$line'))}] ) } spids: [1312] ) ] ) ] ) ) (C {(source)} { (DQ (braced_var_sub token: (Token id:Id.VSub_Name val:BASH_SOURCE span_id:1326) bracket_op: (bracket_op.ArrayIndex expr:(arith_expr.ArithWord w:{(Id.Lit_Digits 0)})) suffix_op: (suffix_op.Unary op_id:Id.VOp1_Percent arg_word:{(Id.Lit_Slash /) ('*')}) ) ) (/bashttpd.conf) } ) (C {(fail_with)} {(500)}) ] )