2024-10-05 16:10:21 +02:00
# SPDX-License-Identifier: AGPL-3.0-or-later
2025-08-09 23:03:30 +02:00
# pylint: disable=missing-module-docstring,disable=missing-class-docstring,invalid-name,line-too-long
2024-10-05 16:10:21 +02:00
from parameterized . parameterized import parameterized
2024-12-15 09:59:50 +01:00
from flask_babel import gettext
import searx . plugins
import searx . preferences
import searx . limiter
import searx . botdetection
from searx . extended_types import sxng_request
from searx . result_types import Answer
2024-10-05 16:10:21 +02:00
from tests import SearxTestCase
2024-12-15 09:59:50 +01:00
from . test_plugins import do_post_search
2024-10-05 16:10:21 +02:00
2024-12-15 09:59:50 +01:00
class PluginIPSelfInfo ( SearxTestCase ) :
2024-10-05 16:10:21 +02:00
def setUp ( self ) :
2024-12-15 09:59:50 +01:00
super ( ) . setUp ( )
2025-03-20 07:47:38 +01:00
engines = { }
2024-12-15 09:59:50 +01:00
self . storage = searx . plugins . PluginStorage ( )
2025-03-20 07:47:38 +01:00
self . storage . load_settings ( { " searx.plugins.self_info.SXNGPlugin " : { " active " : True } } )
2024-12-15 09:59:50 +01:00
self . storage . init ( self . app )
2025-03-20 07:47:38 +01:00
self . pref = searx . preferences . Preferences ( [ " simple " ] , [ " general " ] , engines , self . storage )
2024-12-15 09:59:50 +01:00
self . pref . parse_dict ( { " locale " : " en " } )
2025-03-20 07:47:38 +01:00
2024-12-15 09:59:50 +01:00
cfg = searx . limiter . get_cfg ( )
searx . botdetection . init ( cfg , None )
2024-10-05 16:10:21 +02:00
def test_plugin_store_init ( self ) :
2024-12-15 09:59:50 +01:00
self . assertEqual ( 1 , len ( self . storage ) )
2025-08-09 23:03:30 +02:00
def test_IPv4_X_Forwarded_For ( self ) :
headers = { " X-Forwarded-For " : " 1.2.3.4, 127.0.0.1 " }
answer = gettext ( " Your IP is: " ) + " 1.2.3.4 "
result = self . client . post ( " /search " , data = { " q " : " ip " } , headers = headers )
self . assertIn ( answer , str ( result . data ) )
result = self . client . post ( " /search " , data = { " q " : " ip " , " pageno " : " 2 " } , headers = headers )
self . assertNotIn ( answer , str ( result . data ) )
def test_IPv6_X_Forwarded_For ( self ) :
headers = {
" X-Forwarded-For " : " fd0f:a306:f289:0000:0000:0000:ffff:bbbb, ::1, 127.0.0.1 " ,
" X-Real-IP " : " fd0f:a306:f289:0000:0000:0000:ffff:aaaa " ,
}
# value from X-Forwarded-For should win
answer = gettext ( " Your IP is: " ) + " fd0f:a306:f289::ffff:bbbb "
result = self . client . post ( " /search " , data = { " q " : " ip " } , headers = headers )
self . assertIn ( answer , str ( result . data ) )
def test_IPv6_X_Forwarded_For_all_trusted ( self ) :
headers = {
" X-Forwarded-For " : " 127.0.0.1, 127.0.0.2, 127.0.0.3, ::1 " ,
}
# value from X-Forwarded-For should win
answer = gettext ( " Your IP is: " ) + " 127.0.0.1 "
result = self . client . post ( " /search " , data = { " q " : " ip " } , headers = headers )
self . assertIn ( answer , str ( result . data ) )
def test_IPv6_X_Real_IP ( self ) :
headers = {
" X-Real-IP " : " fd0f:a306:f289:0000:0000:0000:ffff:aaaa " ,
}
# X-Forwarded-For is not set, X-Real-IP should win
answer = gettext ( " Your IP is: " ) + " fd0f:a306:f289::ffff:aaaa "
result = self . client . post ( " /search " , data = { " q " : " ip " } , headers = headers )
self . assertIn ( answer , str ( result . data ) )
def test_REMOTE_ADDR_is_invalid ( self ) :
# X-Forwarded-For and X-Real-IP ar unset and REMOTE_ADDR is invalid
answer = gettext ( " Your IP is: " ) + " 100:: "
headers = { }
environ_overrides = { " REMOTE_ADDR " : " 1.2.3.4.5 " }
with self . assertLogs ( " searx.botdetection " , level = " ERROR " ) as ctx :
result = self . client . post ( " /search " , data = { " q " : " ip " } , headers = headers , environ_overrides = environ_overrides )
self . assertIn ( answer , str ( result . data ) )
self . assertIn (
" ERROR:searx.botdetection:REMOTE_ADDR: ' 1.2.3.4.5 ' does not appear to be an IPv4 or IPv6 address / discard REMOTE_ADDR from WSGI environment " ,
ctx . output ,
)
def test_X_Real_IP_is_invalid ( self ) :
# when a client fakes a X-Real-IP header with an invalid IP 1.2.3.4.5 in
answer = gettext ( " Your IP is: " ) + " 96.7.128.186 "
headers = { " X-Real-IP " : " 1.2.3.4.5 " , " X-Forwarded-For " : " 96.7.128.186, 127.0.0.1 " }
environ_overrides = { " REMOTE_ADDR " : " 127.0.0.1 " }
with self . assertLogs ( " searx.botdetection " , level = " ERROR " ) as ctx :
result = self . client . post ( " /search " , data = { " q " : " ip " } , headers = headers , environ_overrides = environ_overrides )
self . assertIn ( answer , str ( result . data ) )
self . assertIn (
" ERROR:searx.botdetection:X-Real-IP: ' 1.2.3.4.5 ' does not appear to be an IPv4 or IPv6 address / discard HTTP_X_REAL_IP from WSGI environment " ,
ctx . output ,
)
def test_X_Forwarded_For_is_invalid ( self ) :
# when a client fakes a X-Forwarded-For header with an invalid IP
# 1.2.3.4.5 in and the Proxy set a X-Real-IP
answer = gettext ( " Your IP is: " ) + " 96.7.128.186 "
headers = {
" X-Forwarded-For " : " 1.2.3.4, 1.2.3.4.5, 127.0.0.1 " ,
" X-Real-IP " : " 96.7.128.186 " ,
}
with self . assertLogs ( " searx.botdetection " , level = " ERROR " ) as ctx :
result = self . client . post ( " /search " , data = { " q " : " ip " } , headers = headers )
self . assertIn ( answer , str ( result . data ) )
self . assertIn (
" ERROR:searx.botdetection:X-Forwarded-For: ' 1.2.3.4.5 ' does not appear to be an IPv4 or IPv6 address / discard HTTP_X_FORWARDED_FOR from WSGI environment " ,
ctx . output ,
)
2024-10-05 16:10:21 +02:00
@parameterized.expand (
[
2024-12-15 09:59:50 +01:00
" user-agent " ,
" USER-AgenT lorem ipsum " ,
2024-10-05 16:10:21 +02:00
]
)
def test_user_agent_in_answer ( self , query : str ) :
2024-12-15 09:59:50 +01:00
query = " user-agent "
with self . app . test_request_context ( ) :
sxng_request . preferences = self . pref
sxng_request . user_agent = " Dummy agent " # type: ignore
2025-01-27 16:43:43 +01:00
answer = Answer ( answer = gettext ( " Your user-agent is: " ) + " Dummy agent " )
2024-12-15 09:59:50 +01:00
search = do_post_search ( query , self . storage , pageno = 1 )
self . assertIn ( answer , search . result_container . answers )
search = do_post_search ( query , self . storage , pageno = 2 )
self . assertEqual ( list ( search . result_container . answers ) , [ ] )