Skip to content

Commit 5c0f26d

Browse files
committed
added status server
1 parent 7879e6f commit 5c0f26d

File tree

4 files changed

+106
-19
lines changed

4 files changed

+106
-19
lines changed
Binary file not shown.

src/client/http_client.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ def final_request (method="GET",url="/",headers = None,body =""):
110110
endpoint = "/api/Authentication/register"
111111

112112
body = json.dumps({
113-
"id":33590,
113+
"id":3591,
114114
"name": "User_335",
115-
"userName": "username_33590",
115+
"userName": "username_3591",
116116
"email": "example3@gmail.com",
117117
"password": "Password_333!",
118118
"userRole": "Technician",
@@ -141,9 +141,11 @@ def final_request (method="GET",url="/",headers = None,body =""):
141141
print("Encabezados:", response.headers)
142142
print("Cuerpo:", response.body[:500])
143143

144-
# Case 3: HTTPS
145-
response = final_request("GET","https://jsonplaceholder.typicode.com", headers={}, body="")
144+
# Case 3: GET DownTrack
146145

146+
endpoint = "/api/Employee/GET_ALL"
147+
response = final_request("GET", f"{host}{endpoint}", headers={}, body="")
148+
147149
print("Código de estado:", response.code)
148150
print("Encabezados:", response.headers)
149151
print("Cuerpo:", response.body[:500])

src/server/server.py

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import datetime
55
import zlib
66
from logger import logger
7+
from status import HTTP_STATUS_CODES
78

89
# Configuración del servidor
910
HOST = '0.0.0.0' # Escucha en todas las interfaces
@@ -22,7 +23,7 @@ def start(self):
2223
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Permite reutilizar el puerto
2324
server_socket.bind((self.host, self.port))
2425
server_socket.listen(5)
25-
26+
2627
logger.info(f"Servidor HTTP en {self.host}:{self.port}")
2728

2829
while True:
@@ -44,6 +45,7 @@ def handle_client(self, client_socket):
4445

4546
except Exception as e:
4647
logger.error(f"Error al procesar la solicitud: {e}")
48+
client_socket.sendall(self.http_response(500, "Internal Server Error", "An unexpected error occurred.").encode())
4749

4850
finally:
4951
client_socket.close()
@@ -79,41 +81,94 @@ def parse_headers(self, header_lines):
7981
def build_response(self, method, path, headers, body):
8082
"""Genera respuestas HTTP según el método y la ruta solicitada."""
8183

82-
logger.info(f"Method : {method}")
84+
logger.info(f"Method : {method} - Path: {path}")
85+
86+
# 414 - URI Too Long
87+
if len(path) > 2048:
88+
return self.http_response(414)
89+
90+
# Verificar si el cliente tiene una versión válida del recurso (usando If-Modified-Since o If-None-Match)
91+
last_modified = self.get_last_modified(path) # Esta función puede devolver la última fecha de modificación del recurso
92+
if last_modified:
93+
if "If-Modified-Since" in headers:
94+
if_modified_since = headers["If-Modified-Since"]
95+
if if_modified_since >= last_modified:
96+
return self.http_response(304, headers=headers) # No se ha modificado, devolver 304
97+
98+
if "If-None-Match" in headers:
99+
if_none_match = headers["If-None-Match"]
100+
if if_none_match == self.get_etag(path): # Comparar con el ETag
101+
return self.http_response(304, headers=headers) # ETag coincide, devolver 304
102+
103+
# Redirecciones
104+
if path == "/old-page":
105+
return self.http_response(301, location="/new-page")
106+
107+
if path == "/temp-move":
108+
return self.http_response(302, location="/temporary-page") # 302 Found
109+
110+
111+
# Si la ruta no existe
112+
if path != "/":
113+
return self.http_response(404)
114+
115+
# 411 - Length Required
116+
if method in ["POST", "PUT"] and "Content-Length" not in headers:
117+
return self.http_response(411)
118+
119+
# 415 - Unsupported Media Type
120+
if method in ["POST", "PUT"]:
121+
supported_types = ["application/json", "application/x-www-form-urlencoded", "text/plain"]
122+
if "Content-Type" in headers and headers["Content-Type"] not in supported_types:
123+
return self.http_response(415)
124+
83125
if method == "GET":
84-
return self.http_response(200, "OK", "Hello, GET!")
126+
return self.http_response(200, "Hello, GET!")
85127

86128
elif method == "POST":
87-
return self.http_response(200, "OK", f"Received POST: {body}")
129+
return self.http_response(200, f"Received POST: {body}")
88130

89131
elif method == "HEAD":
90-
return self.http_response(200, "OK", "", include_body=False)
132+
return self.http_response(200, "", include_body=False)
91133

92134
elif method == "PUT":
93-
return self.http_response(200, "OK", "PUT request successful!")
135+
return self.http_response(200, "PUT request successful!")
94136

95137
elif method == "DELETE":
96-
return self.http_response(200, "OK", "DELETE request successful!")
138+
return self.http_response(200, "DELETE request successful!")
97139

98140
elif method == "OPTIONS":
99-
return self.http_response(200, "OK", "", headers={"Allow": "OPTIONS, GET, POST, HEAD, PUT, DELETE, TRACE, CONNECT"})
141+
return self.http_response(200, "", headers={"Allow": "OPTIONS, GET, POST, HEAD, PUT, DELETE, TRACE, CONNECT"})
100142

101143
elif method == "TRACE":
102-
return self.http_response(200, "OK", f"TRACE received:\n{headers}")
144+
return self.http_response(200, f"TRACE received:\n{headers}")
103145

104146
else:
105-
return self.http_response(405, "Method Not Allowed", "This method is not supported.")
147+
return self.http_response(405)
106148

107-
def http_response(self, status_code, reason, body, headers=None, include_body=True):
149+
def http_response(self, status_code, reason, body, headers=None,location=None, include_body=True):
108150
"""Construye una respuesta HTTP válida con headers y cuerpo."""
109151
headers = headers or {}
110152
headers["Server"] = "CustomHTTPServer/1.0"
111153
headers["Date"] = datetime.datetime.now(datetime.timezone.utc).strftime("%a, %d %b %Y %H:%M:%S GMT")
112154

155+
156+
# Obtener el mensaje de estado y la descripción
157+
reason, default_body = HTTP_STATUS_CODES.get(status_code, ("Unknown", "Unknown error"))
158+
159+
# Manejo de redirecciones (301, 302, etc.)
160+
if status_code in [301, 302, 304] and location:
161+
headers["Location"] = location
162+
body = f"Redirecting to {location}"
163+
164+
# Si no se especifica un body, usar el mensaje por defecto
165+
if not body and include_body:
166+
body = default_body
167+
113168
# Verificar si el cliente acepta gzip
114-
acceptes_encoding = headers.get("accept-encoding","")
115-
accepts_gzip = "gzip" in acceptes_encoding
116-
accepts_deflate = "deflate" in acceptes_encoding
169+
accept_encoding = headers.get("Accept-Encoding","").lower()
170+
accepts_gzip = "gzip" in accept_encoding
171+
accepts_deflate = "deflate" in accept_encoding
117172

118173
if include_body:
119174
body_bytes = body.encode()
@@ -135,7 +190,7 @@ def http_response(self, status_code, reason, body, headers=None, include_body=Tr
135190
response += f"{key}: {value}\r\n"
136191
response += "\r\n"
137192

138-
logger.debug(f"Respuesta generada: {status_code} {reason}")
193+
logger.debug(f"Respuesta generada: {status_code} {reason} {'-> ' + location if location else ''}")
139194
return response + body_bytes.decode()
140195

141196

src/server/status.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
HTTP_STATUS_CODES = {
2+
# Informativos
3+
100: ("Continue", "The server has received the request headers and the client should proceed to send the body."),
4+
101: ("Switching Protocols", "The server is switching protocols as requested."),
5+
6+
# Éxito
7+
200: ("OK", "Request processed successfully."),
8+
201: ("Created", "The resource was successfully created."),
9+
204: ("No Content", "The server successfully processed the request, but is not returning any content."),
10+
11+
# Redirección
12+
301: ("Moved Permanently", "The requested resource has been permanently moved."),
13+
302: ("Found", "The requested resource is temporarily at a different location."),
14+
304: ("Not Modified", "The resource has not changed since the last request."),
15+
16+
# Errores del cliente
17+
400: ("Bad Request", "Invalid request format."),
18+
401: ("Unauthorized", "Authentication is required to access this resource."),
19+
403: ("Forbidden", "You do not have permission to access this resource."),
20+
404: ("Not Found", "The requested resource was not found."),
21+
405: ("Method Not Allowed", "This method is not supported."),
22+
411: ("Length Required", "Content-Length header is required for POST and PUT."),
23+
414: ("URI Too Long", "Requested URL is too long."),
24+
415: ("Unsupported Media Type", "This content type is not supported."),
25+
26+
# Errores del servidor
27+
500: ("Internal Server Error", "An unexpected error occurred."),
28+
501: ("Not Implemented", "This method is not supported by the server."),
29+
503: ("Service Unavailable", "The server is currently unable to handle the request."),
30+
}

0 commit comments

Comments
 (0)