Skip to content

Commit b919e63

Browse files
committed
enhance HTTP client GUI with request history and improved layout
1 parent 7e161b9 commit b919e63

File tree

1 file changed

+48
-150
lines changed

1 file changed

+48
-150
lines changed

src/client/http_client_gui.py

Lines changed: 48 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,3 @@
1-
# import customtkinter as ctk
2-
# import json
3-
# from tkinter import messagebox
4-
# import client_cli
5-
6-
# class HttpClientGUI:
7-
# def __init__(self, parent):
8-
# ctk.set_appearance_mode("dark")
9-
# ctk.set_default_color_theme("blue")
10-
# self.root = parent
11-
# self.root.title("HTTP Client")
12-
# self.root.geometry("600x550")
13-
# self.root.grid_columnconfigure(1, weight=1)
14-
15-
# # URL
16-
# ctk.CTkLabel(parent, text="URL:").grid(row=0, column=0, padx=10, pady=5, sticky="w")
17-
# self.url_entry = ctk.CTkEntry(parent, width=400)
18-
# self.url_entry.grid(row=0, column=1, padx=10, pady=5, sticky="ew")
19-
20-
# # Method
21-
# ctk.CTkLabel(parent, text="Method:").grid(row=1, column=0, padx=10, pady=5, sticky="w")
22-
# self.method_var = ctk.StringVar(value="GET")
23-
# self.method_menu = ctk.CTkOptionMenu(parent, variable=self.method_var, values=["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "CONNECT", "TRACE", "LINK", "UNLINK", "CUSTOM"], command=self.toggle_body_state)
24-
# self.method_menu.grid(row=1, column=1, padx=10, pady=5, sticky="ew")
25-
26-
# # Headers
27-
# ctk.CTkLabel(parent, text="Headers (JSON):").grid(row=2, column=0, padx=10, pady=5, sticky="w")
28-
# self.headers_entry = ctk.CTkEntry(parent, width=400)
29-
# self.headers_entry.grid(row=2, column=1, padx=10, pady=5, sticky="ew")
30-
31-
# # Body
32-
# ctk.CTkLabel(parent, text="Body (JSON):").grid(row=3, column=0, padx=10, pady=5, sticky="w")
33-
# self.body_text = ctk.CTkTextbox(parent, width=400, height=100)
34-
# self.body_text.grid(row=3, column=1, padx=10, pady=5, sticky="ew")
35-
36-
# # Send Button
37-
# self.send_button = ctk.CTkButton(parent, text="Send", command=self.send_request)
38-
# self.send_button.grid(row=4, column=1, pady=10)
39-
40-
# # Response
41-
# ctk.CTkLabel(parent, text="Response:").grid(row=5, column=0, padx=10, pady=5, sticky="w")
42-
# self.response_text = ctk.CTkTextbox(parent, width=400, height=150, state="disabled")
43-
# self.response_text.grid(row=5, column=1, padx=10, pady=5, sticky="ew")
44-
45-
# self.toggle_body_state("GET")
46-
47-
# def toggle_body_state(self, method):
48-
# self.body_text.delete("1.0", "end")
49-
50-
# if method == "GET":
51-
# self.body_text.configure(state="disabled")
52-
# else:
53-
# self.body_text.configure(state="normal")
54-
55-
# def send_request(self):
56-
# url = self.url_entry.get()
57-
# method = self.method_var.get()
58-
# headers = self.headers_entry.get()
59-
# body = self.body_text.get("1.0", "end").strip()
60-
61-
# try:
62-
# headers = json.loads(headers) if headers else {}
63-
# except json.JSONDecodeError:
64-
# messagebox.showerror("Error", "Headers must be valid JSON.\nExample:\n{\"Content-Type\": \"application/json\"}")
65-
# return
66-
67-
# try:
68-
# body = json.loads(body) if body else ""
69-
# except json.JSONDecodeError:
70-
# messagebox.showerror("Error", "Body must be valid JSON.")
71-
# return
72-
73-
# try:
74-
# response_text = client_cli.run_client(method, url, headers, body)
75-
76-
# # Dividir encabezado y cuerpo
77-
# header_part, body_part = response_text.split("\n\n", 1) if "\n\n" in response_text else (response_text, "")
78-
79-
# # Obtener el código de estado HTTP
80-
# first_line = header_part.split("\n")[0] # Primera línea "HTTP/1.1 200 OK"
81-
# status_code = int(first_line.split(" ")[1]) # Extraer código (ej: 200)
82-
83-
# # Configurar colores según código de estado
84-
# self.response_text.configure(state="normal")
85-
# self.response_text.delete("1.0", "end")
86-
87-
# # Colorear encabezados (azul)
88-
# self.response_text.insert("end", header_part + "\n\n", "header")
89-
90-
# # Si el cuerpo es JSON, lo formateamos bonito
91-
# try:
92-
# body_json = json.loads(body_part)
93-
# formatted_body = json.dumps(body_json, indent=2)
94-
# except json.JSONDecodeError:
95-
# formatted_body = body_part # Si no es JSON, mostrarlo tal cual
96-
97-
# # Insertar el cuerpo con color blanco
98-
# self.response_text.insert("end", formatted_body, "body")
99-
100-
# # Aplicar colores
101-
# self.response_text.tag_config("header", foreground="blue")
102-
# self.response_text.tag_config("body", foreground="white")
103-
104-
# # Código de estado en color según resultado
105-
# if 200 <= status_code < 300:
106-
# self.response_text.tag_config("status", foreground="green") # Éxito
107-
# elif 400 <= status_code < 600:
108-
# self.response_text.tag_config("status", foreground="red") # Error
109-
110-
# self.response_text.configure(state="disabled")
111-
# except Exception as e:
112-
# messagebox.showerror("Error", f"Request failed: {e}")
113-
114-
115-
# if __name__ == "__main__":
116-
# root = ctk.CTk()
117-
# app = HttpClientGUI(root)
118-
# root.mainloop()
119-
1201
import customtkinter as ctk
1212
import json
1223
from tkinter import messagebox
@@ -128,39 +9,55 @@ def __init__(self, parent):
1289
ctk.set_default_color_theme("blue")
12910
self.root = parent
13011
self.root.title("HTTP Client")
131-
self.root.geometry("600x550")
12+
self.root.geometry("700x650") # Aumentar tamaño para historial
13213
self.root.grid_columnconfigure(1, weight=1)
13314

15+
# Estilo general
16+
font_style = ("Arial", 14)
17+
18+
# Historial de solicitudes
19+
self.history = []
20+
13421
# URL
135-
ctk.CTkLabel(parent, text="URL:").grid(row=0, column=0, padx=10, pady=5, sticky="w")
136-
self.url_entry = ctk.CTkEntry(parent, width=400)
22+
ctk.CTkLabel(parent, text="🌐 URL:", font=font_style).grid(row=0, column=0, padx=10, pady=5, sticky="w")
23+
self.url_entry = ctk.CTkEntry(parent, width=500, font=font_style)
13724
self.url_entry.grid(row=0, column=1, padx=10, pady=5, sticky="ew")
13825

13926
# Method
140-
ctk.CTkLabel(parent, text="Method:").grid(row=1, column=0, padx=10, pady=5, sticky="w")
27+
ctk.CTkLabel(parent, text="📡 Method:", font=font_style).grid(row=1, column=0, padx=10, pady=5, sticky="w")
14128
self.method_var = ctk.StringVar(value="GET")
142-
self.method_menu = ctk.CTkOptionMenu(parent, variable=self.method_var, values=["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "CONNECT", "TRACE", "LINK", "UNLINK", "CUSTOM"], command=self.toggle_body_state)
29+
self.method_menu = ctk.CTkOptionMenu(parent, variable=self.method_var,
30+
values=["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "CONNECT", "TRACE", "LINK", "UNLINK", "CUSTOM"],
31+
command=self.toggle_body_state, font=font_style)
14332
self.method_menu.grid(row=1, column=1, padx=10, pady=5, sticky="ew")
14433

14534
# Headers
146-
ctk.CTkLabel(parent, text="Headers (JSON):").grid(row=2, column=0, padx=10, pady=5, sticky="w")
147-
self.headers_entry = ctk.CTkEntry(parent, width=400)
35+
ctk.CTkLabel(parent, text="📝 Headers (JSON):", font=font_style).grid(row=2, column=0, padx=10, pady=5, sticky="w")
36+
self.headers_entry = ctk.CTkTextbox(parent, width=500, height=60, font=font_style)
14837
self.headers_entry.grid(row=2, column=1, padx=10, pady=5, sticky="ew")
14938

15039
# Body
151-
ctk.CTkLabel(parent, text="Body (JSON):").grid(row=3, column=0, padx=10, pady=5, sticky="w")
152-
self.body_text = ctk.CTkTextbox(parent, width=400, height=100)
40+
ctk.CTkLabel(parent, text="📦 Body (JSON):", font=font_style).grid(row=3, column=0, padx=10, pady=5, sticky="w")
41+
self.body_text = ctk.CTkTextbox(parent, width=500, height=100, font=font_style)
15342
self.body_text.grid(row=3, column=1, padx=10, pady=5, sticky="ew")
15443

15544
# Send Button
156-
self.send_button = ctk.CTkButton(parent, text="Send", command=self.send_request)
157-
self.send_button.grid(row=4, column=1, pady=10)
45+
self.send_button = ctk.CTkButton(parent, text="🚀 Send Request", command=self.send_request, font=font_style)
46+
self.send_button.grid(row=4, column=1, pady=15)
15847

15948
# Response
160-
ctk.CTkLabel(parent, text="Response:").grid(row=5, column=0, padx=10, pady=5, sticky="w")
161-
self.response_text = ctk.CTkTextbox(parent, width=400, height=150, state="disabled")
49+
ctk.CTkLabel(parent, text="📩 Response:", font=font_style).grid(row=5, column=0, padx=10, pady=5, sticky="w")
50+
self.response_text = ctk.CTkTextbox(parent, width=500, height=200, font=font_style, state="disabled")
16251
self.response_text.grid(row=5, column=1, padx=10, pady=5, sticky="ew")
16352

53+
# Historial de solicitudes
54+
ctk.CTkLabel(parent, text="📜 Request History:", font=font_style).grid(row=6, column=0, padx=10, pady=5, sticky="w")
55+
self.history_var = ctk.StringVar(value="No history yet")
56+
self.history_menu = ctk.CTkOptionMenu(parent, variable=self.history_var, values=["No history yet"], font=font_style)
57+
self.history_menu.grid(row=6, column=1, padx=10, pady=5, sticky="ew")
58+
self.load_history_button = ctk.CTkButton(parent, text="🔄 Load Request", command=self.load_request, font=font_style)
59+
self.load_history_button.grid(row=7, column=1, pady=10)
60+
16461
self.toggle_body_state("GET")
16562

16663
def toggle_body_state(self, method):
@@ -174,7 +71,7 @@ def toggle_body_state(self, method):
17471
def send_request(self):
17572
url = self.url_entry.get()
17673
method = self.method_var.get()
177-
headers = self.headers_entry.get()
74+
headers = self.headers_entry.get("1.0", "end").strip()
17875
body = self.body_text.get("1.0", "end").strip()
17976

18077
try:
@@ -192,28 +89,29 @@ def send_request(self):
19289
try:
19390
response_text = client_cli.run_client(method, url, headers, body)
19491

195-
# Dividir encabezado y cuerpo
196-
header_part, body_part = response_text.split("\n\n", 1) if "\n\n" in response_text else (response_text, "")
197-
92+
# Guardar en historial
93+
self.history.append((url, method, json.dumps(headers, indent=2), json.dumps(body, indent=2)))
94+
self.history_menu.configure(values=[f"{i+1}: {h[1]} {h[0]}" for i, h in enumerate(self.history)])
95+
self.history_var.set(f"{len(self.history)}: {method} {url}")
96+
19897
self.response_text.configure(state="normal")
19998
self.response_text.delete("1.0", "end")
200-
201-
# Insertar encabezados tal cual
202-
self.response_text.insert("end", header_part + "\n\n")
203-
204-
# Si el cuerpo es JSON, formatearlo bonito
205-
try:
206-
body_json = json.loads(body_part)
207-
formatted_body = json.dumps(body_json, indent=2)
208-
except json.JSONDecodeError:
209-
formatted_body = body_part # Si no es JSON, mostrarlo tal cual
210-
211-
# Insertar el cuerpo formateado
212-
self.response_text.insert("end", formatted_body)
213-
99+
self.response_text.insert("end", response_text)
214100
self.response_text.configure(state="disabled")
215101
except Exception as e:
216102
messagebox.showerror("Error", f"Request failed: {e}")
103+
104+
def load_request(self):
105+
index = int(self.history_var.get().split(":")[0]) - 1
106+
if 0 <= index < len(self.history):
107+
url, method, headers, body = self.history[index]
108+
self.url_entry.delete(0, "end")
109+
self.url_entry.insert(0, url)
110+
self.method_var.set(method)
111+
self.headers_entry.delete("1.0", "end")
112+
self.headers_entry.insert("end", headers)
113+
self.body_text.delete("1.0", "end")
114+
self.body_text.insert("end", body)
217115

218116
if __name__ == "__main__":
219117
root = ctk.CTk()

0 commit comments

Comments
 (0)