mirror of
				https://github.com/dgtlmoon/changedetection.io.git
				synced 2025-10-31 14:47:21 +00:00 
			
		
		
		
	Compare commits
	
		
			9 Commits
		
	
	
		
			3393-unrea
			...
			1448-basic
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 719d24ad23 | ||
|   | 7ded35a3ac | ||
|   | 6ace90a8ea | ||
|   | 6663768396 | ||
|   | 284d0a0246 | ||
|   | 04429b88ee | ||
|   | d11c581089 | ||
|   | 5e5fe6dc05 | ||
|   | 46ab2846d0 | 
| @@ -700,6 +700,7 @@ def changedetection_app(config=None, datastore_o=None): | ||||
|                                      form=form, | ||||
|                                      has_default_notification_urls=True if len(datastore.data['settings']['application']['notification_urls']) else False, | ||||
|                                      has_empty_checktime=using_default_check_time, | ||||
|                                      has_extra_headers_file=watch.has_extra_headers_file or datastore.has_extra_headers_file, | ||||
|                                      is_html_webdriver=is_html_webdriver, | ||||
|                                      jq_support=jq_support, | ||||
|                                      playwright_enabled=os.getenv('PLAYWRIGHT_DRIVER_URL', False), | ||||
| @@ -1444,6 +1445,7 @@ def check_for_new_version(): | ||||
|         # Check daily | ||||
|         app.config.exit.wait(86400) | ||||
|  | ||||
|  | ||||
| def notification_runner(): | ||||
|     global notification_debug_log | ||||
|     from datetime import datetime | ||||
|   | ||||
| @@ -49,3 +49,15 @@ class model(dict): | ||||
|     def __init__(self, *arg, **kw): | ||||
|         super(model, self).__init__(*arg, **kw) | ||||
|         self.update(self.base_config) | ||||
|  | ||||
|  | ||||
| def parse_headers_from_text_file(filepath): | ||||
|     headers = {} | ||||
|     with open(filepath, 'r') as f: | ||||
|         for l in f.readlines(): | ||||
|             l = l.strip() | ||||
|             if not l.startswith('#') and ':' in l: | ||||
|                 (k, v) = l.split(':') | ||||
|                 headers[k.strip()] = v.strip() | ||||
|  | ||||
|     return headers | ||||
| @@ -473,6 +473,40 @@ class model(dict): | ||||
|         # None is set | ||||
|         return False | ||||
|  | ||||
|     @property | ||||
|     def has_extra_headers_file(self): | ||||
|         if os.path.isfile(os.path.join(self.watch_data_dir, 'headers.txt')): | ||||
|             return True | ||||
|  | ||||
|         for f in self.all_tags: | ||||
|             fname = "headers-"+re.sub(r'[\W_]', '', f).lower().strip() + ".txt" | ||||
|             filepath = os.path.join(self.__datastore_path, fname) | ||||
|             if os.path.isfile(filepath): | ||||
|                 return True | ||||
|  | ||||
|         return False | ||||
|  | ||||
|     def get_all_headers(self): | ||||
|         from .App import parse_headers_from_text_file | ||||
|         headers = self.get('headers', {}).copy() | ||||
|         # Available headers on the disk could 'headers.txt' in the watch data dir | ||||
|         filepath = os.path.join(self.watch_data_dir, 'headers.txt') | ||||
|         try: | ||||
|             if os.path.isfile(filepath): | ||||
|                 headers.update(parse_headers_from_text_file(filepath)) | ||||
|         except Exception as e: | ||||
|             print(f"ERROR reading headers.txt at {filepath}", str(e)) | ||||
|  | ||||
|         # Or each by tag, as tagname.txt in the main datadir | ||||
|         for f in self.all_tags: | ||||
|             fname = "headers-"+re.sub(r'[\W_]', '', f).lower().strip() + ".txt" | ||||
|             filepath = os.path.join(self.__datastore_path, fname) | ||||
|             try: | ||||
|                 if os.path.isfile(filepath): | ||||
|                     headers.update(parse_headers_from_text_file(filepath)) | ||||
|             except Exception as e: | ||||
|                 print(f"ERROR reading headers.txt at {filepath}", str(e)) | ||||
|         return headers | ||||
|  | ||||
|     def get_last_fetched_before_filters(self): | ||||
|         import brotli | ||||
|   | ||||
| @@ -70,10 +70,9 @@ class perform_site_check(difference_detection_processor): | ||||
|         # Unset any existing notification error | ||||
|         update_obj = {'last_notification_error': False, 'last_error': False} | ||||
|  | ||||
|         extra_headers = watch.get('headers', []) | ||||
|  | ||||
|         # Tweak the base config with the per-watch ones | ||||
|         request_headers = deepcopy(self.datastore.data['settings']['headers']) | ||||
|         extra_headers = watch.get_all_headers() | ||||
|         request_headers = self.datastore.get_all_headers() | ||||
|         request_headers.update(extra_headers) | ||||
|  | ||||
|         # https://github.com/psf/requests/issues/4525 | ||||
|   | ||||
| @@ -3,7 +3,7 @@ from flask import ( | ||||
| ) | ||||
|  | ||||
| from . model import App, Watch | ||||
| from copy import deepcopy | ||||
| from copy import deepcopy, copy | ||||
| from os import path, unlink | ||||
| from threading import Lock | ||||
| import json | ||||
| @@ -474,8 +474,6 @@ class ChangeDetectionStore: | ||||
|         return proxy_list if len(proxy_list) else None | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|     def get_preferred_proxy_for_watch(self, uuid): | ||||
|         """ | ||||
|         Returns the preferred proxy by ID key | ||||
| @@ -507,6 +505,25 @@ class ChangeDetectionStore: | ||||
|  | ||||
|         return None | ||||
|  | ||||
|     @property | ||||
|     def has_extra_headers_file(self): | ||||
|         filepath = os.path.join(self.datastore_path, 'headers.txt') | ||||
|         return os.path.isfile(filepath) | ||||
|  | ||||
|     def get_all_headers(self): | ||||
|         from .model.App import parse_headers_from_text_file | ||||
|         headers = copy(self.data['settings'].get('headers', {})) | ||||
|  | ||||
|         filepath = os.path.join(self.datastore_path, 'headers.txt') | ||||
|         try: | ||||
|             if os.path.isfile(filepath): | ||||
|                 headers.update(parse_headers_from_text_file(filepath)) | ||||
|         except Exception as e: | ||||
|             print(f"ERROR reading headers.txt at {filepath}", str(e)) | ||||
|  | ||||
|         return headers | ||||
|  | ||||
|  | ||||
|     # Run all updates | ||||
|     # IMPORTANT - Each update could be run even when they have a new install and the schema is correct | ||||
|     #             So therefor - each `update_n` should be very careful about checking if it needs to actually run | ||||
|   | ||||
| @@ -152,6 +152,15 @@ | ||||
| {{ render_field(form.headers, rows=5, placeholder="Example | ||||
| Cookie: foobar | ||||
| User-Agent: wonderbra 1.0") }} | ||||
|  | ||||
|                         <div class="pure-form-message-inline"> | ||||
|                             {% if has_extra_headers_file %} | ||||
|                                 <strong>Alert! Extra headers file found and will be added to this watch!</strong> | ||||
|                             {% else %} | ||||
|                                 Headers can be also read from a file in your data-directory <a href="https://github.com/dgtlmoon/changedetection.io/wiki/Adding-headers-from-an-external-file">Read more here</a> | ||||
|                             {% endif %} | ||||
|                         </div> | ||||
|  | ||||
|                     </div> | ||||
|                     <div class="pure-control-group" id="request-body"> | ||||
|                                         {{ render_field(form.body, rows=5, placeholder="Example | ||||
|   | ||||
| @@ -14,13 +14,16 @@ global app | ||||
|  | ||||
| def cleanup(datastore_path): | ||||
|     # Unlink test output files | ||||
|     files = ['output.txt', | ||||
|              'url-watches.json', | ||||
|              'secret.txt', | ||||
|              'notification.txt', | ||||
|              'count.txt', | ||||
|              'endpoint-content.txt' | ||||
|                  ] | ||||
|     files = [ | ||||
|         'count.txt', | ||||
|         'endpoint-content.txt' | ||||
|         'headers.txt', | ||||
|         'headers-testtag.txt', | ||||
|         'notification.txt', | ||||
|         'secret.txt', | ||||
|         'url-watches.json', | ||||
|         'output.txt', | ||||
|     ] | ||||
|     for file in files: | ||||
|         try: | ||||
|             os.unlink("{}/{}".format(datastore_path, file)) | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| import json | ||||
| import os | ||||
| import time | ||||
| from flask import url_for | ||||
| from . util import set_original_response, set_modified_response, live_server_setup | ||||
| from . util import set_original_response, set_modified_response, live_server_setup, wait_for_all_checks, extract_UUID_from_client | ||||
|  | ||||
| def test_setup(live_server): | ||||
|     live_server_setup(live_server) | ||||
| @@ -234,3 +235,72 @@ def test_method_in_request(client, live_server): | ||||
|     # Should be only one with method set to PATCH | ||||
|     assert watches_with_method == 1 | ||||
|  | ||||
|     res = client.get(url_for("form_delete", uuid="all"), follow_redirects=True) | ||||
|     assert b'Deleted' in res.data | ||||
|  | ||||
| def test_headers_textfile_in_request(client, live_server): | ||||
|     #live_server_setup(live_server) | ||||
|     # Add our URL to the import page | ||||
|     test_url = url_for('test_headers', _external=True) | ||||
|  | ||||
|     # Add the test URL twice, we will check | ||||
|     res = client.post( | ||||
|         url_for("import_page"), | ||||
|         data={"urls": test_url}, | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     assert b"1 Imported" in res.data | ||||
|  | ||||
|     time.sleep(1) | ||||
|  | ||||
|  | ||||
|     # Add some headers to a request | ||||
|     res = client.post( | ||||
|         url_for("edit_page", uuid="first"), | ||||
|         data={ | ||||
|               "url": test_url, | ||||
|               "tag": "testtag", | ||||
|               "fetch_backend": "html_requests", | ||||
|               "headers": "xxx:ooo\ncool:yeah\r\n"}, | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     assert b"Updated watch." in res.data | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     with open('test-datastore/headers-testtag.txt', 'w') as f: | ||||
|         f.write("tag-header: test") | ||||
|  | ||||
|     with open('test-datastore/headers.txt', 'w') as f: | ||||
|         f.write("global-header: nice\r\nnext-global-header: nice") | ||||
|  | ||||
|     with open('test-datastore/'+extract_UUID_from_client(client)+'/headers.txt', 'w') as f: | ||||
|         f.write("watch-header: nice") | ||||
|  | ||||
|     client.get(url_for("form_watch_checknow"), follow_redirects=True) | ||||
|  | ||||
|     # Give the thread time to pick it up | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get(url_for("edit_page", uuid="first")) | ||||
|     assert b"Extra headers file found and will be added to this watch" in res.data | ||||
|  | ||||
|     # Not needed anymore | ||||
|     os.unlink('test-datastore/headers.txt') | ||||
|     os.unlink('test-datastore/headers-testtag.txt') | ||||
|     os.unlink('test-datastore/'+extract_UUID_from_client(client)+'/headers.txt') | ||||
|     # The service should echo back the request verb | ||||
|     res = client.get( | ||||
|         url_for("preview_page", uuid="first"), | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|  | ||||
|     assert b"Global-Header:nice" in res.data | ||||
|     assert b"Next-Global-Header:nice" in res.data | ||||
|     assert b"Xxx:ooo" in res.data | ||||
|     assert b"Watch-Header:nice" in res.data | ||||
|     assert b"Tag-Header:test" in res.data | ||||
|  | ||||
|  | ||||
|     #unlink headers.txt on start/stop | ||||
|     res = client.get(url_for("form_delete", uuid="all"), follow_redirects=True) | ||||
|     assert b'Deleted' in res.data | ||||
		Reference in New Issue
	
	Block a user