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
-
120
1
import customtkinter as ctk
121
2
import json
122
3
from tkinter import messagebox
@@ -128,39 +9,55 @@ def __init__(self, parent):
128
9
ctk .set_default_color_theme ("blue" )
129
10
self .root = parent
130
11
self .root .title ("HTTP Client" )
131
- self .root .geometry ("600x550" )
12
+ self .root .geometry ("700x650" ) # Aumentar tamaño para historial
132
13
self .root .grid_columnconfigure (1 , weight = 1 )
133
14
15
+ # Estilo general
16
+ font_style = ("Arial" , 14 )
17
+
18
+ # Historial de solicitudes
19
+ self .history = []
20
+
134
21
# 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 )
137
24
self .url_entry .grid (row = 0 , column = 1 , padx = 10 , pady = 5 , sticky = "ew" )
138
25
139
26
# 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" )
141
28
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 )
143
32
self .method_menu .grid (row = 1 , column = 1 , padx = 10 , pady = 5 , sticky = "ew" )
144
33
145
34
# 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 )
148
37
self .headers_entry .grid (row = 2 , column = 1 , padx = 10 , pady = 5 , sticky = "ew" )
149
38
150
39
# 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 )
153
42
self .body_text .grid (row = 3 , column = 1 , padx = 10 , pady = 5 , sticky = "ew" )
154
43
155
44
# 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 )
158
47
159
48
# 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" )
162
51
self .response_text .grid (row = 5 , column = 1 , padx = 10 , pady = 5 , sticky = "ew" )
163
52
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
+
164
61
self .toggle_body_state ("GET" )
165
62
166
63
def toggle_body_state (self , method ):
@@ -174,7 +71,7 @@ def toggle_body_state(self, method):
174
71
def send_request (self ):
175
72
url = self .url_entry .get ()
176
73
method = self .method_var .get ()
177
- headers = self .headers_entry .get ()
74
+ headers = self .headers_entry .get ("1.0" , "end" ). strip ( )
178
75
body = self .body_text .get ("1.0" , "end" ).strip ()
179
76
180
77
try :
@@ -192,28 +89,29 @@ def send_request(self):
192
89
try :
193
90
response_text = client_cli .run_client (method , url , headers , body )
194
91
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
+
198
97
self .response_text .configure (state = "normal" )
199
98
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 )
214
100
self .response_text .configure (state = "disabled" )
215
101
except Exception as e :
216
102
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 )
217
115
218
116
if __name__ == "__main__" :
219
117
root = ctk .CTk ()
0 commit comments