# frozen_string_literal: true# Released under the MIT License.# Copyright, 2018-2025, by Samuel Williams.require_relative"../request"moduleAsyncmoduleHTTPmoduleProtocolmoduleHTTP1classRequest<Protocol::Requestdefself.valid_path?(target)iftarget.start_with?("/")returntrueelsiftarget=="*"returntrueelsereturnfalseendendURI_PATTERN=%r{\A(?<scheme>[^:/]+)://(?<authority>[^/]+)(?<path>.*)\z}defself.read(connection)connection.read_requestdo|authority,method,target,version,headers,body|ifmethod==::Protocol::HTTP::Methods::CONNECT# We put the target into the authority field for CONNECT requests, as per HTTP/2 semantics.self.new(connection,nil,target,method,nil,version,headers,body)elsifvalid_path?(target)# This is a valid request.self.new(connection,nil,authority,method,target,version,headers,body)elsifmatch=target.match(URI_PATTERN)# We map the incoming absolute URI target to the scheme, authority, and path fields of the request.self.new(connection,match[:scheme],match[:authority],method,match[:path],version,headers,body)else# This is an invalid request.raise::Protocol::HTTP1::BadRequest.new("Invalid request target: #{target}")endendendUPGRADE="upgrade"definitialize(connection,scheme,authority,method,path,version,headers,body)@connection=connection# HTTP/1 requests with an upgrade header (which can contain zero or more values) are extracted into the protocol field of the request, and we expect a response to select one of those protocols with a status code of 101 Switching Protocols.protocol=headers.delete("upgrade")super(scheme,authority,method,path,version,headers,body,protocol,self.public_method(:write_interim_response))enddefconnection@connectionenddefhijack?trueenddefhijack!@connection.hijack!enddefwrite_interim_response(status,headers=nil)@connection.write_interim_response(@version,status,headers)endendendendendend