atomicshop 2.20.8__py3-none-any.whl → 2.21.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of atomicshop might be problematic. Click here for more details.

atomicshop/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  """Atomic Basic functions and classes to make developer life easier"""
2
2
 
3
3
  __author__ = "Den Kras"
4
- __version__ = '2.20.8'
4
+ __version__ = '2.21.1'
@@ -6,16 +6,15 @@ from . import import_config
6
6
 
7
7
  # CONFIG = None
8
8
  LIST_OF_BOOLEANS: list = [
9
+ ('dnstcp', 'offline'),
9
10
  ('dns', 'enable'),
10
- ('dns', 'offline_mode'),
11
- ('dns', 'resolve_to_tcp_server_only_engine_domains'),
12
- ('dns', 'resolve_to_tcp_server_all_domains'),
13
- ('dns', 'resolve_regular'),
11
+ ('dns', 'resolve_by_engine'),
12
+ ('dns', 'resolve_regular_pass_thru'),
13
+ ('dns', 'resolve_all_domains_to_ipv4'),
14
14
  ('dns', 'set_default_dns_gateway_to_localhost'),
15
15
  ('dns', 'set_default_dns_gateway_to_default_interface_ipv4'),
16
16
  ('tcp', 'enable'),
17
- ('tcp', 'engines_usage'),
18
- ('tcp', 'server_response_mode'),
17
+ ('tcp', 'no_engines_usage_to_listen_addresses'),
19
18
  ('logrec', 'enable_request_response_recordings_in_logs'),
20
19
  ('certificates', 'install_ca_certificate_to_root_store'),
21
20
  ('certificates', 'uninstall_unused_ca_certificates_with_mitm_ca_name'),
@@ -32,6 +31,7 @@ LIST_OF_BOOLEANS: list = [
32
31
 
33
32
 
34
33
  TOML_TO_STATIC_CATEGORIES: dict = {
34
+ 'dnstcp': 'MainConfig',
35
35
  'dns': 'DNSServer',
36
36
  'tcp': 'TCPServer',
37
37
  'logrec': 'LogRec',
@@ -40,6 +40,10 @@ TOML_TO_STATIC_CATEGORIES: dict = {
40
40
  'process_name': 'ProcessName'
41
41
  }
42
42
 
43
+ # noinspection PyTypeChecker
44
+ ENGINES_LIST: list = None # list[initialize_engines.ModuleCategory]
45
+ REFERENCE_MODULE = None # initialize_engines.ModuleCategory
46
+
43
47
 
44
48
  class MainConfig:
45
49
  LOGGER_NAME: str = 'network'
@@ -61,6 +65,7 @@ class MainConfig:
61
65
  # Default server certificate file name and path.
62
66
  default_server_certificate_filename = f'{default_server_certificate_name}.pem'
63
67
  default_server_certificate_filepath: str = None
68
+ offline: bool = False
64
69
 
65
70
  @classmethod
66
71
  def update(cls):
@@ -77,32 +82,34 @@ class DNSServer:
77
82
  enable: bool
78
83
  offline_mode: bool
79
84
 
80
- listening_interface: str
81
- listening_port: int
85
+ listening_address: str
82
86
  forwarding_dns_service_ipv4: str
83
87
  cache_timeout_minutes: int
84
88
 
85
- resolve_to_tcp_server_only_engine_domains: bool
86
- resolve_to_tcp_server_all_domains: bool
87
- resolve_regular: bool
88
- target_tcp_server_ipv4: str
89
+ resolve_by_engine: bool
90
+ resolve_regular_pass_thru: bool
91
+ resolve_all_domains_to_ipv4_enable: bool
92
+ target_ipv4: str
89
93
 
90
94
  set_default_dns_gateway: str
91
95
  set_default_dns_gateway_to_localhost: bool
92
96
  set_default_dns_gateway_to_default_interface_ipv4: bool
93
97
 
98
+ # Convertable variables.
99
+ resolve_all_domains_to_ipv4: dict
100
+
101
+ # Static variables.
102
+ forwarding_dns_service_port: int = 53
103
+
94
104
 
95
105
  @dataclass
96
106
  class TCPServer:
97
107
  enable: bool
108
+ no_engines_usage_to_listen_addresses_enable: bool
109
+ no_engines_listening_address_list: list[str]
98
110
 
99
- engines_usage: bool
100
- server_response_mode: bool
101
-
102
- listening_address_list: list[str]
103
-
104
- forwarding_dns_service_ipv4_list___only_for_localhost: list[str]
105
-
111
+ # Convertable variables.
112
+ no_engines_usage_to_listen_addresses: dict
106
113
 
107
114
  @dataclass
108
115
  class LogRec:
@@ -161,7 +168,7 @@ def load_config(config_toml_file_path: str):
161
168
  MainConfig.update()
162
169
 
163
170
  # Load the configuration file.
164
- result = import_config.import_config_file(config_toml_file_path)
171
+ result = import_config.import_config_files(config_toml_file_path)
165
172
  return result
166
173
 
167
174
 
@@ -1,7 +1,6 @@
1
1
  from datetime import datetime
2
2
  import threading
3
3
  import queue
4
- import copy
5
4
  import socket
6
5
 
7
6
  from ..wrappers.socketw import receiver, sender, socket_client, base
@@ -182,30 +181,33 @@ def thread_worker_main(
182
181
  network_logger.info("Thread Finished. Will continue listening on the Main thread")
183
182
 
184
183
  def create_responder_response(client_message: ClientMessage) -> list[bytes]:
185
- # Since we're in response mode, we'll record the request anyway, after the responder did its job.
186
- client_message.info = "In Server Response Mode"
187
-
188
- # If it's the first cycle and the protocol is Websocket, then we'll create the HTTP Handshake
189
- # response automatically.
190
- if protocol == 'Websocket' and client_receive_count == 1:
191
- responses: list = list()
192
- responses.append(
193
- websocket_parse.create_byte_http_response(client_message.request_raw_bytes))
184
+ if client_message.action == 'service_connect':
185
+ return responder.create_connect_response(client_message)
194
186
  else:
195
- # Creating response for parsed message and printing
196
- responses: list = responder.create_response(client_message)
187
+ # Since we're in response mode, we'll record the request anyway, after the responder did its job.
188
+ # client_message.info = "In Server Response Mode"
189
+
190
+ # If it's the first cycle and the protocol is Websocket, then we'll create the HTTP Handshake
191
+ # response automatically.
192
+ if protocol == 'Websocket' and client_receive_count == 1:
193
+ responses: list = list()
194
+ responses.append(
195
+ websocket_parse.create_byte_http_response(client_message.request_raw_bytes))
196
+ else:
197
+ # Creating response for parsed message and printing
198
+ responses: list = responder.create_response(client_message)
197
199
 
198
- # Output first 100 characters of all the responses in the list.
199
- for response_raw_bytes_single in responses:
200
- responder.logger.info(f"{response_raw_bytes_single[0: 100]}...")
200
+ # Output first 100 characters of all the responses in the list.
201
+ for response_raw_bytes_single in responses:
202
+ responder.logger.info(f"{response_raw_bytes_single[0: 100]}...")
201
203
 
202
- return responses
204
+ return responses
203
205
 
204
206
  def create_client_socket(client_message: ClientMessage):
205
207
  # If there is a custom certificate for the client for this domain, then we'll use it.
206
208
  # noinspection PyTypeChecker
207
209
  custom_client_pem_certificate_path: str = None
208
- for subdomain, pem_file_path in mtls_dict.items():
210
+ for subdomain, pem_file_path in found_domain_module.mtls.items():
209
211
  if subdomain == client_message.server_name:
210
212
  custom_client_pem_certificate_path = pem_file_path
211
213
  break
@@ -217,8 +219,7 @@ def thread_worker_main(
217
219
  service_name=client_message.server_name,
218
220
  service_port=client_message.destination_port,
219
221
  tls=is_tls,
220
- dns_servers_list=(
221
- config_static.TCPServer.forwarding_dns_service_ipv4_list___only_for_localhost),
222
+ dns_servers_list=[config_static.DNSServer.forwarding_dns_service_ipv4],
222
223
  logger=network_logger,
223
224
  custom_pem_client_certificate_file_path=custom_client_pem_certificate_path,
224
225
  enable_sslkeylogfile_env_to_client_ssl_context=(
@@ -304,53 +305,11 @@ def thread_worker_main(
304
305
 
305
306
  return client_message
306
307
 
307
- def responder_thread_worker():
308
- nonlocal exception_or_close_in_receiving_thread
309
-
310
- client_message: ClientMessage = client_message_first_start()
311
- try:
312
- while True:
313
- client_message = responder_queue.get()
314
- print_api(f"Got message from queue, action: [{client_message.action}]", logger=network_logger, logger_method='info')
315
-
316
- # If the message is not a ClientMessage object, then we'll break the loop, since it is the exit signal.
317
- if not isinstance(client_message, ClientMessage):
318
- return
319
-
320
- if client_message.action == 'service_connect':
321
- raw_responses: list[bytes] = responder.create_connect_response(client_message)
322
- else:
323
- raw_responses: list[bytes] = create_responder_response(client_message)
324
- print_api(f"Got responses from responder, count: [{len(raw_responses)}]", logger=network_logger, logger_method='info')
325
-
326
- is_socket_closed: bool = False
327
- for response_raw_bytes in raw_responses:
328
- client_message.reinitialize_dynamic_vars()
329
- client_message.timestamp = datetime.now()
330
- client_message.response_raw_bytes = response_raw_bytes
331
-
332
- record_and_statistics_write(client_message)
333
-
334
- error_on_send: str = sender.Sender(
335
- ssl_socket=client_socket, class_message=client_message.response_raw_bytes,
336
- logger=network_logger).send()
337
-
338
- # If there was problem with sending data, we'll break the main while loop.
339
- if error_on_send:
340
- client_message.errors.append(error_on_send)
341
- record_and_statistics_write(client_message)
342
- is_socket_closed = True
343
-
344
- if is_socket_closed:
345
- exception_or_close_in_receiving_thread = True
346
- return
347
- except Exception as exc:
348
- handle_exceptions_on_sub_connection_thread(client_message, client_exception_queue, exc)
349
-
350
308
  def receive_send_start(
351
309
  receiving_socket,
352
310
  sending_socket = None,
353
- exception_queue: queue.Queue = None
311
+ exception_queue: queue.Queue = None,
312
+ client_connection_message: ClientMessage = None
354
313
  ):
355
314
  nonlocal client_receive_count
356
315
  nonlocal server_receive_count
@@ -371,59 +330,87 @@ def thread_worker_main(
371
330
  raise ValueError(f"Unknown side of the socket: {receiving_socket}")
372
331
 
373
332
  while True:
374
- client_message.reinitialize_dynamic_vars()
333
+ # pass the socket connect to responder.
334
+ if side == 'Service' and client_connection_message:
335
+ client_message = client_connection_message
375
336
 
376
- if side == 'Client':
377
- client_receive_count += 1
378
- current_count = client_receive_count
337
+ bytes_to_send_list: list[bytes] = create_responder_response(client_message)
338
+ print_api(f"Got responses from responder, count: [{len(bytes_to_send_list)}]", logger=network_logger,
339
+ logger_method='info')
379
340
  else:
380
- server_receive_count += 1
381
- current_count = server_receive_count
341
+ client_message.reinitialize_dynamic_vars()
382
342
 
383
- network_logger.info(
384
- f"Initializing Receiver for {side} cycle: {str(current_count)}")
343
+ if side == 'Client':
344
+ client_receive_count += 1
345
+ current_count = client_receive_count
346
+ else:
347
+ server_receive_count += 1
348
+ current_count = server_receive_count
385
349
 
386
- # Getting message from the client over the socket using specific class.
387
- received_raw_data, is_socket_closed, error_message = receiver.Receiver(
388
- ssl_socket=receiving_socket, logger=network_logger).receive()
350
+ network_logger.info(
351
+ f"Initializing Receiver for {side} cycle: {str(current_count)}")
389
352
 
390
- # Getting current time of message received, either from client or service.
391
- client_message.timestamp = datetime.now()
353
+ # Getting message from the client over the socket using specific class.
354
+ received_raw_data, is_socket_closed, error_message = receiver.Receiver(
355
+ ssl_socket=receiving_socket, logger=network_logger).receive()
392
356
 
393
- # In case of client socket, we'll process the raw data specifically for the client.
394
- if side == 'Client':
395
- process_client_raw_data(received_raw_data, error_message, client_message)
396
- client_message.action = 'client_receive'
397
- # In case of service socket, we'll process the raw data specifically for the service.
398
- else:
399
- process_server_raw_data(received_raw_data, error_message, client_message)
400
- client_message.action = 'service_receive'
357
+ # Getting current time of message received, either from client or service.
358
+ client_message.timestamp = datetime.now()
401
359
 
402
- # If there was an exception in the service thread, then receiving empty bytes doesn't mean that
403
- # the socket was closed by the other side, it means that the service thread closed the socket.
404
- if (received_raw_data == b'' or error_message) and exception_or_close_in_receiving_thread:
405
- print_api("Both sockets are closed, breaking the loop", logger=network_logger,
406
- logger_method='info')
407
- return
360
+ # In case of client socket, we'll process the raw data specifically for the client.
361
+ if side == 'Client':
362
+ process_client_raw_data(received_raw_data, error_message, client_message)
363
+ client_message.action = 'client_receive'
364
+ # In case of service socket, we'll process the raw data specifically for the service.
365
+ else:
366
+ process_server_raw_data(received_raw_data, error_message, client_message)
367
+ client_message.action = 'service_receive'
368
+
369
+ # If there was an exception in the service thread, then receiving empty bytes doesn't mean that
370
+ # the socket was closed by the other side, it means that the service thread closed the socket.
371
+ if (received_raw_data == b'' or error_message) and exception_or_close_in_receiving_thread:
372
+ print_api("Both sockets are closed, breaking the loop", logger=network_logger,
373
+ logger_method='info')
374
+ return
408
375
 
409
- # We will record only if there was no closing signal, because if there was, it means that we initiated
410
- # the close on the opposite socket.
411
- record_and_statistics_write(client_message)
376
+ # We will record only if there was no closing signal, because if there was, it means that we initiated
377
+ # the close on the opposite socket.
378
+ record_and_statistics_write(client_message)
412
379
 
413
- if is_socket_closed:
414
- exception_or_close_in_receiving_thread = True
415
- finish_thread()
416
- return
380
+ # Now send it to requester/responder.
381
+ if side == 'Client':
382
+ # Send to requester.
383
+ bytes_to_send_list: list[bytes] = [client_message.request_raw_bytes]
384
+ else:
385
+ bytes_to_send_list: list[bytes] = create_responder_response(client_message)
386
+ print_api(f"Got responses from responder, count: [{len(bytes_to_send_list)}]",
387
+ logger=network_logger,
388
+ logger_method='info')
389
+
390
+ if is_socket_closed:
391
+ exception_or_close_in_receiving_thread = True
392
+ finish_thread()
393
+ return
417
394
 
418
- # If we're in response mode, execute responder.
419
- if config_static.TCPServer.server_response_mode:
420
- responder_queue.put(copy.deepcopy(client_message))
421
- else:
422
- # if side == 'Client':
423
- # raise NotImplementedError
395
+ # If nothing was passed from the responder, and the client message is the connection message, then we'll skip to the next iteration.
396
+ if not bytes_to_send_list and client_connection_message:
397
+ client_connection_message = None
398
+ continue
399
+
400
+ is_socket_closed: bool = False
401
+ for bytes_to_send_single in bytes_to_send_list:
424
402
  client_message.reinitialize_dynamic_vars()
403
+ client_message.timestamp = datetime.now()
404
+
405
+ if side == 'Client':
406
+ client_message.request_raw_bytes = bytes_to_send_single
407
+ else:
408
+ client_message.response_raw_bytes = bytes_to_send_single
409
+
410
+ record_and_statistics_write(client_message)
411
+
425
412
  error_on_send: str = sender.Sender(
426
- ssl_socket=sending_socket, class_message=received_raw_data,
413
+ ssl_socket=sending_socket, class_message=bytes_to_send_single,
427
414
  logger=network_logger).send()
428
415
 
429
416
  if error_on_send:
@@ -440,9 +427,11 @@ def thread_worker_main(
440
427
  # If the socket was closed on message receive, then we'll break the loop only after send.
441
428
  if is_socket_closed or error_on_send:
442
429
  exception_or_close_in_receiving_thread = True
443
- responder_queue.put('exit')
444
430
  finish_thread()
445
431
  return
432
+
433
+ # For next iteration to start in case this iteration was responsible to process connection message, we need to set it to None.
434
+ client_connection_message = None
446
435
  except Exception as exc:
447
436
  # If the sockets were already closed, then there is nothing to do here besides log.
448
437
  # if (isinstance(exc, OSError) and exc.errno == 10038 and
@@ -471,7 +460,6 @@ def thread_worker_main(
471
460
  # record_and_statistics_write(client_message)
472
461
 
473
462
  finish_thread()
474
- responder_queue.put('exit')
475
463
  exception_queue.put(exc)
476
464
 
477
465
  def handle_exceptions_on_main_connection_thread(
@@ -517,23 +505,26 @@ def thread_worker_main(
517
505
 
518
506
  # Loading parser by domain, if there is no parser for current domain - general reference parser is loaded.
519
507
  # These should be outside any loop and initialized only once entering the thread.
520
- parser, responder, recorder_no_init, mtls_dict = assign_class_by_domain(
521
- engines_usage=config_static.TCPServer.engines_usage,
508
+ found_domain_module = assign_class_by_domain(
522
509
  engines_list=engines_list,
523
510
  message_domain_name=server_name,
524
- reference_module=reference_module,
525
- logger=network_logger
511
+ reference_module=reference_module
526
512
  )
513
+ parser = found_domain_module.parser_class_object
514
+ responder = found_domain_module.responder_class_object()
515
+ recorder = found_domain_module.recorder_class_object(record_path=config_static.LogRec.recordings_path)
516
+
517
+ network_logger.info(f"Assigned Modules for [{server_name}]: "
518
+ f"{parser.__name__}, "
519
+ f"{responder.__class__.__name__}, "
520
+ f"{recorder.__class__.__name__}")
527
521
 
528
- recorder = recorder_no_init(record_path=config_static.LogRec.recordings_path)
529
522
 
530
523
  # Initializing the client message object with current thread's data.
531
524
  # This is needed only to skip error alerts after 'try'.
532
525
  client_message_connection: ClientMessage = ClientMessage()
533
526
  # This is needed to indicate if there was an exception or socket was closed in any of the receiving thread.
534
527
  exception_or_close_in_receiving_thread: bool = False
535
- # Responder queue for ClientMessage objects.
536
- responder_queue: queue.Queue = queue.Queue()
537
528
  # Queue for http request URI paths.
538
529
  http_path_queue: queue.Queue = queue.Queue()
539
530
 
@@ -543,86 +534,67 @@ def thread_worker_main(
543
534
  client_name = socket.gethostbyaddr(client_ip)[0]
544
535
  destination_port = client_socket.getsockname()[1]
545
536
 
546
- if config_static.TCPServer.server_response_mode:
547
- # If in response mode, then we'll get the TCP server's input address.
537
+ if config_static.MainConfig.offline:
538
+ # If in offline mode, then we'll get the TCP server's input address.
548
539
  server_ip = client_socket.getsockname()[0]
549
540
  else:
550
- # If not in response mode, we will get the ip from the socket that will connect later to the service.
541
+ # If not in offline mode, we will get the ip from the socket that will connect later to the service.
551
542
  server_ip = ""
552
543
 
553
544
  network_logger.info(f"Thread Created - Client [{client_ip}:{source_port}] | "
554
545
  f"Destination service: [{server_name}:{destination_port}]")
555
546
 
556
- # If we're in response mode, we'll start the responder thread.
557
- if config_static.TCPServer.server_response_mode:
558
- responder_thread: threading.Thread = threading.Thread(
559
- target=responder_thread_worker, name=f"Thread-{thread_id}-Responder", daemon=True)
560
- responder_thread.start()
561
- else:
562
- # noinspection PyTypeChecker
563
- responder_thread = None
564
-
565
547
  service_client = None
566
548
  client_receive_count: int = 0
567
549
  server_receive_count: int = 0
568
550
  client_message_connection = client_message_first_start()
569
551
 
570
- # If we're not in response mode, then we'll create the client socket to the service.
552
+ # If we're not in offline mode, then we'll create the client socket to the service.
571
553
  # noinspection PyTypeChecker
572
554
  connection_error: str = None
573
555
  service_socket_instance = None
574
- if not config_static.TCPServer.server_response_mode:
575
- # If "service_client" object is not defined, we'll define it.
576
- # If it's defined, then there's still active "ssl_socket" with connection to the service domain.
577
- if not service_client:
578
- service_client = create_client_socket(client_message_connection)
579
- service_socket_instance, connection_error = service_client.service_connection()
580
- # Now we'll update the server IP with the IP of the service.
581
- server_ip = service_socket_instance.getpeername()[0]
582
- client_message_connection.server_ip = server_ip
583
- else:
584
- client_message_connection.timestamp = datetime.now()
585
- client_message_connection.action = 'service_connect'
586
- client_message_connection.info = 'Server Response Mode'
587
- responder_queue.put(copy.deepcopy(client_message_connection))
588
-
589
- if connection_error:
590
- client_message_connection.timestamp = datetime.now()
591
- client_message_connection.errors.append(connection_error)
592
- client_message_connection.action = 'service_connect'
593
- record_and_statistics_write(client_message_connection)
556
+ client_message_connection.action = 'service_connect'
557
+ client_message_connection.timestamp = datetime.now()
558
+
559
+ if config_static.MainConfig.offline:
560
+ client_message_connection.info = 'Offline Mode'
594
561
  else:
562
+ service_client = create_client_socket(client_message_connection)
563
+ service_socket_instance, connection_error = service_client.service_connection()
564
+ # Now we'll update the server IP with the IP of the service.
565
+ server_ip = service_socket_instance.getpeername()[0]
566
+ client_message_connection.server_ip = server_ip
567
+
568
+ if connection_error:
569
+ client_message_connection.errors.append(connection_error)
570
+ record_and_statistics_write(client_message_connection)
571
+
572
+ if not connection_error:
595
573
  client_exception_queue: queue.Queue = queue.Queue()
596
574
  client_thread = threading.Thread(
597
- target=receive_send_start, args=(client_socket, service_socket_instance, client_exception_queue),
575
+ target=receive_send_start,
576
+ args=(client_socket, service_socket_instance, client_exception_queue, None),
598
577
  name=f"Thread-{thread_id}-Client")
599
578
  client_thread.daemon = True
600
579
  client_thread.start()
601
580
 
602
- if not config_static.TCPServer.server_response_mode:
603
- service_exception_queue: queue.Queue = queue.Queue()
604
- service_thread = threading.Thread(
605
- target=receive_send_start, args=(service_socket_instance, client_socket, service_exception_queue),
606
- name=f"Thread-{thread_id}-Service")
607
- service_thread.daemon = True
608
- service_thread.start()
581
+ service_exception_queue: queue.Queue = queue.Queue()
582
+ service_thread = threading.Thread(
583
+ target=receive_send_start,
584
+ args=(service_socket_instance, client_socket, service_exception_queue, client_message_connection),
585
+ name=f"Thread-{thread_id}-Service")
586
+ service_thread.daemon = True
587
+ service_thread.start()
609
588
 
610
589
  client_thread.join()
611
- if config_static.TCPServer.server_response_mode:
612
- responder_thread.join()
613
- else:
614
- service_thread.join()
590
+ service_thread.join()
615
591
 
616
592
  # If there was an exception in any of the threads, then we'll raise it here.
617
593
  if not client_exception_queue.empty():
618
594
  raise client_exception_queue.get()
619
- if not config_static.TCPServer.server_response_mode:
620
- if not service_exception_queue.empty():
621
- raise service_exception_queue.get()
595
+ if not service_exception_queue.empty():
596
+ raise service_exception_queue.get()
622
597
 
623
598
  finish_thread()
624
599
  except Exception as e:
625
- if not client_message_connection.timestamp:
626
- client_message_connection.timestamp = datetime.now()
627
-
628
600
  handle_exceptions_on_main_connection_thread(e, client_message_connection)
@@ -110,48 +110,49 @@ class ResponderParent:
110
110
  headers: dict,
111
111
  body: bytes
112
112
  ) -> bytes:
113
+ # noinspection GrazieInspection
113
114
  """
114
- Create genuine response from input parameters.
115
- ---------------
116
- The response is built from:
117
- HTTP-Version HTTP-Status HTTP-Status-String\r\n
118
- Headers1: Value\r\n
119
- Headers2: Value\r\n
120
- \r\n # This is meant to end the headers' section
121
- Body\r\n\r\n # In most cases Body is ended with '\r\n\r\n'
122
- ---------------
123
- Example for 200 response:
124
- HTTP/1.1 200 OK\r\n
125
- Cache-Control: max-age=86400\r\n
126
- Content-Type: application/json; charset=utf-8\r\n
127
- \r\n
128
- {"id":1,"name":"something"}
129
- ---------------
130
- The final response will look like oneline string:
131
- HTTP/1.1 200 OK\r\nCache-Control: max-age=86400\r\n
132
- Content-Type: application/json; charset=utf-8\r\n\r\n{"id":1,"name":"something"}
133
- ---------------
134
- You can create response as:
135
-
136
- ...HTTP/1.1 200 OK
137
- header1: value
138
- header2: value
139
-
140
- {data: value}...
141
-
142
- Change 3 dots ("...") to 3 double quotes before "HTTP" and after "value}".
143
- This way there will be "\n" added automatically after each line.
144
- While, the HTTP Client does the parsing of the text and not raw data, most probably it will be parsed well,
145
- but genuine responses from HTTP sources come with "\r\n" at the end of the line, so better use these for
146
- better compatibility.
147
- ---------------
148
-
149
- :param http_version: HTTP Version of Response in HTTP Status line.
150
- :param status_code: HTTP Status Code of Response in HTTP Status line.
151
- :param headers: HTTP Headers of Response.
152
- :param body: HTTP body data of Response, bytes.
153
- :return: bytes of the response.
154
- """
115
+ Create genuine response from input parameters.
116
+ ---------------
117
+ The response is built from:
118
+ HTTP-Version HTTP-Status HTTP-Status-String\r\n
119
+ Headers1: Value\r\n
120
+ Headers2: Value\r\n
121
+ \r\n # This is meant to end the headers' section
122
+ Body\r\n\r\n # In most cases Body is ended with '\r\n\r\n'
123
+ ---------------
124
+ Example for 200 response:
125
+ HTTP/1.1 200 OK\r\n
126
+ Cache-Control: max-age=86400\r\n
127
+ Content-Type: application/json; charset=utf-8\r\n
128
+ \r\n
129
+ {"id":1,"name":"something"}
130
+ ---------------
131
+ The final response will look like oneline string:
132
+ HTTP/1.1 200 OK\r\nCache-Control: max-age=86400\r\n
133
+ Content-Type: application/json; charset=utf-8\r\n\r\n{"id":1,"name":"something"}
134
+ ---------------
135
+ You can create response as:
136
+
137
+ ...HTTP/1.1 200 OK
138
+ header1: value
139
+ header2: value
140
+
141
+ {data: value}...
142
+
143
+ Change 3 dots ("...") to 3 double quotes before "HTTP" and after "value}".
144
+ This way there will be "\n" added automatically after each line.
145
+ While, the HTTP Client does the parsing of the text and not raw data, most probably it will be parsed well,
146
+ but genuine responses from HTTP sources come with "\r\n" at the end of the line, so better use these for
147
+ better compatibility.
148
+ ---------------
149
+
150
+ :param http_version: HTTP Version of Response in HTTP Status line.
151
+ :param status_code: HTTP Status Code of Response in HTTP Status line.
152
+ :param headers: HTTP Headers of Response.
153
+ :param body: HTTP body data of Response, bytes.
154
+ :return: bytes of the response.
155
+ """
155
156
 
156
157
  try:
157
158
  # Building full status string line and the "\r\n" to the end of the status line
@@ -201,6 +202,5 @@ class ResponderParent:
201
202
  def create_response(self, class_client_message: ClientMessage):
202
203
  """ This function should be overridden in the child class. """
203
204
 
204
- _ = class_client_message
205
- response_bytes_list: list[bytes] = list()
205
+ response_bytes_list: list[bytes] = [class_client_message.response_raw_bytes]
206
206
  return response_bytes_list