Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/httpretty/http.py: 72%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

29 statements  

1# #!/usr/bin/env python 

2# -*- coding: utf-8 -*- 

3# <HTTPretty - HTTP client mock for Python> 

4# Copyright (C) <2011-2021> Gabriel Falcão <gabriel@nacaolivre.org> 

5# 

6# Permission is hereby granted, free of charge, to any person 

7# obtaining a copy of this software and associated documentation 

8# files (the "Software"), to deal in the Software without 

9# restriction, including without limitation the rights to use, 

10# copy, modify, merge, publish, distribute, sublicense, and/or sell 

11# copies of the Software, and to permit persons to whom the 

12# Software is furnished to do so, subject to the following 

13# conditions: 

14# 

15# The above copyright notice and this permission notice shall be 

16# included in all copies or substantial portions of the Software. 

17# 

18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 

19# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 

20# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 

21# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 

22# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 

23# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 

24# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 

25# OTHER DEALINGS IN THE SOFTWARE. 

26from __future__ import unicode_literals 

27 

28import re 

29from .compat import BaseClass 

30from .utils import decode_utf8 

31 

32 

33STATUSES = { 

34 100: "Continue", 

35 101: "Switching Protocols", 

36 102: "Processing", 

37 200: "OK", 

38 201: "Created", 

39 202: "Accepted", 

40 203: "Non-Authoritative Information", 

41 204: "No Content", 

42 205: "Reset Content", 

43 206: "Partial Content", 

44 207: "Multi-Status", 

45 208: "Already Reported", 

46 226: "IM Used", 

47 300: "Multiple Choices", 

48 301: "Moved Permanently", 

49 302: "Found", 

50 303: "See Other", 

51 304: "Not Modified", 

52 305: "Use Proxy", 

53 306: "Switch Proxy", 

54 307: "Temporary Redirect", 

55 308: "Permanent Redirect", 

56 400: "Bad Request", 

57 401: "Unauthorized", 

58 402: "Payment Required", 

59 403: "Forbidden", 

60 404: "Not Found", 

61 405: "Method Not Allowed", 

62 406: "Not Acceptable", 

63 407: "Proxy Authentication Required", 

64 408: "Request a Timeout", 

65 409: "Conflict", 

66 410: "Gone", 

67 411: "Length Required", 

68 412: "Precondition Failed", 

69 413: "Request Entity Too Large", 

70 414: "Request-URI Too Long", 

71 415: "Unsupported Media Type", 

72 416: "Requested Range Not Satisfiable", 

73 417: "Expectation Failed", 

74 418: "I'm a teapot", 

75 420: "Enhance Your Calm", 

76 421: "Misdirected Request", 

77 422: "Unprocessable Entity", 

78 423: "Locked", 

79 424: "Failed Dependency", 

80 425: "Unordered Collection", 

81 426: "Upgrade Required", 

82 428: "Precondition Required", 

83 429: "Too Many Requests", 

84 431: "Request Header Fields Too Large", 

85 444: "No Response", 

86 449: "Retry With", 

87 450: "Blocked by Windows Parental Controls", 

88 451: "Unavailable For Legal Reasons", 

89 494: "Request Header Too Large", 

90 495: "Cert Error", 

91 496: "No Cert", 

92 497: "HTTP to HTTPS", 

93 499: "Client Closed Request", 

94 500: "Internal Server Error", 

95 501: "Not Implemented", 

96 502: "Bad Gateway", 

97 503: "Service Unavailable", 

98 504: "Gateway Timeout", 

99 505: "HTTP Version Not Supported", 

100 506: "Variant Also Negotiates", 

101 507: "Insufficient Storage", 

102 508: "Loop Detected", 

103 509: "Bandwidth Limit Exceeded", 

104 510: "Not Extended", 

105 511: "Network Authentication Required", 

106 598: "Network read timeout error", 

107 599: "Network connect timeout error", 

108} 

109 

110 

111class HttpBaseClass(BaseClass): 

112 GET = 'GET' 

113 PUT = 'PUT' 

114 POST = 'POST' 

115 DELETE = 'DELETE' 

116 HEAD = 'HEAD' 

117 PATCH = 'PATCH' 

118 OPTIONS = 'OPTIONS' 

119 CONNECT = 'CONNECT' 

120 METHODS = (GET, PUT, POST, DELETE, HEAD, PATCH, OPTIONS, CONNECT) 

121 

122 

123def parse_requestline(s): 

124 """ 

125 http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5 

126 

127 >>> parse_requestline('GET / HTTP/1.0') 

128 ('GET', '/', '1.0') 

129 >>> parse_requestline('post /testurl htTP/1.1') 

130 ('POST', '/testurl', '1.1') 

131 >>> parse_requestline('Im not a RequestLine') 

132 Traceback (most recent call last): 

133 ... 

134 ValueError: Not a Request-Line 

135 """ 

136 methods = '|'.join(HttpBaseClass.METHODS) 

137 m = re.match(r'(' + methods + r')\s+(.*)\s+HTTP/(1.[0|1])', s, re.I) 

138 if m: 

139 return m.group(1).upper(), m.group(2), m.group(3) 

140 else: 

141 raise ValueError('Not a Request-Line') 

142 

143 

144def last_requestline(sent_data): 

145 """ 

146 Find the last line in sent_data that can be parsed with parse_requestline 

147 """ 

148 for line in reversed(sent_data): 

149 try: 

150 parse_requestline(decode_utf8(line)) 

151 except ValueError: 

152 pass 

153 else: 

154 return line