# Path: tests/unit/matchers.py
# def temporary_redirect_to(location):
#     """Return a matcher for any `HTTP 302 Found` redirect to the given URL."""
#     return Any.instance_of(Response).with_attrs(
#         {"status_code": 302, "location": location}
#     )
# 
# Path: via/resources.py
# class QueryURLResource(_URLResource):
#     """Resource for routes expecting urls from the query."""
# 
#     def url_from_query(self):
#         """Get the 'url' parameter from the query.
# 
#         :return: The URL as a string
#         :raise HTTPBadRequest: If the URL is missing or empty
#         :raise BadURL: If the URL is malformed
#         """
#         try:
#             url = self._request.params["url"].strip()
#         except KeyError as err:
#             raise HTTPBadRequest("Required parameter 'url' missing") from err
# 
#         if not url:
#             raise HTTPBadRequest("Required parameter 'url' is blank")
# 
#         return self._normalise_url(url)
# 
# Path: via/views/exceptions.py
# EXCEPTION_MAP = {
#     BadURL: {
#         "title": "The URL isn't valid",
#         "long_description": [
#             "Parts of the URL could be missing or in the wrong format."
#         ],
#         "stage": "request",
#         "retryable": False,
#     },
#     UpstreamTimeout: {
#         "title": "Timeout",
#         "long_description": ["The web page we tried to get took too long to respond."],
#         "stage": "upstream",
#         "retryable": True,
#     },
#     UnhandledUpstreamException: {
#         "title": "Something went wrong",
#         "long_description": ["We experienced an unexpected error."],
#         "stage": "via",
#         "retryable": True,
#     },
#     UpstreamServiceError: {
#         "title": "Could not get web page",
#         "long_description": [
#             "Something went wrong when we tried to get the web page.",
#             "It might be missing or might have returned an error.",
#         ],
#         "stage": "upstream",
#         "retryable": True,
#     },
#     HTTPNotFound: {
#         "title": "Page not found",
#         "long_description": [
#             "The URL you asked for is not part of this service.",
#             "Please check the URL you have entered.",
#         ],
#         "stage": "request",
#         "retryable": False,
#     },
#     HTTPClientError: {
#         "title": "Bad request",
#         "long_description": [
#             "We can't process the request because we don't understand it."
#         ],
#         "stage": "request",
#         "retryable": False,
#     },
# }
# def _get_meta(exception):
# def google_drive_exceptions(exc, request):
# def _serialise_requests_info(request, response):
# def other_exceptions(exc, request):
# def _get_error_body(exc, request):
# def _set_status(exc, request):
# 
# Path: via/views/index.py
# class IndexViews:
#     def __init__(self, context, request):
#         self.context = context
#         self.request = request
#         self.enabled = request.registry.settings["enable_front_page"]
# 
#     @view_config(request_method="GET", renderer="via:templates/index.html.jinja2")
#     def get(self):
#         if not self.enabled:
#             return HTTPNotFound()
# 
#         self.request.response.headers["X-Robots-Tag"] = "all"
# 
#         return {}
# 
#     @view_config(request_method="POST")
#     def post(self):
#         if not self.enabled:
#             return HTTPNotFound()
# 
#         try:
#             url = self.context.url_from_query()
#         except HTTPBadRequest:
#             # If we don't get a URL redirect the user to the index page
#             return HTTPFound(self.request.route_url(route_name="index"))
# 
#         # In order to replicate the URL structure from original Via we need to
#         # create a path like this:
#         # http://via.host/http://proxied.site?query=1
#         # This means we need to pop off the query string and then add it
#         # separately from the URL, otherwise we'll get the query string encoded
#         # inside the URL portion of the path.
# 
#         # `context.url_from_query` protects us from parsing failing
#         parsed = urlparse(url)
#         url_without_query = parsed._replace(query="", fragment="").geturl()
# 
#         return HTTPFound(
#             self.request.route_url(
#                 route_name="proxy", url=url_without_query, _query=parsed.query
#             )
#         )


import pytest
from pyramid.httpexceptions import HTTPFound, HTTPNotFound
from tests.unit.matchers import temporary_redirect_to
from via.resources import QueryURLResource
from via.views.exceptions import BadURL
from via.views.index import IndexViews


class TestIndexViews:
    def test_get(self, views):
        assert views.get() == {}

    def test_post(self, views, pyramid_request):
        pyramid_request.params["url"] = "//site.org?q1=value1&q2=value2"

        redirect = views.post()

        assert isinstance(redirect, HTTPFound)
        assert (
            redirect.location
            == "http://example.com/https://site.org?q1=value1&q2=value2"
        )

    def test_post_with_no_url(self, views, pyramid_request):
        assert "url" not in pyramid_request.params

        redirect = views.post()

        assert redirect == temporary_redirect_to(
            pyramid_request.route_url(route_name="index")
        )

    def test_post_raises_if_url_invalid(self, views, pyramid_request):
        # Set a `url` that causes `urlparse` to throw.
        pyramid_request.params["url"] = "http://::12.34.56.78]/"


# Path: tests/unit/matchers.py
# def temporary_redirect_to(location):
#     """Return a matcher for any `HTTP 302 Found` redirect to the given URL."""
#     return Any.instance_of(Response).with_attrs(
#         {"status_code": 302, "location": location}
#     )
# 
# Path: via/resources.py
# class QueryURLResource(_URLResource):
#     """Resource for routes expecting urls from the query."""
# 
#     def url_from_query(self):
#         """Get the 'url' parameter from the query.
# 
#         :return: The URL as a string
#         :raise HTTPBadRequest: If the URL is missing or empty
#         :raise BadURL: If the URL is malformed
#         """
#         try:
#             url = self._request.params["url"].strip()
#         except KeyError as err:
#             raise HTTPBadRequest("Required parameter 'url' missing") from err
# 
#         if not url:
#             raise HTTPBadRequest("Required parameter 'url' is blank")
# 
#         return self._normalise_url(url)
# 
# Path: via/views/exceptions.py
# EXCEPTION_MAP = {
#     BadURL: {
#         "title": "The URL isn't valid",
#         "long_description": [
#             "Parts of the URL could be missing or in the wrong format."
#         ],
#         "stage": "request",
#         "retryable": False,
#     },
#     UpstreamTimeout: {
#         "title": "Timeout",
#         "long_description": ["The web page we tried to get took too long to respond."],
#         "stage": "upstream",
#         "retryable": True,
#     },
#     UnhandledUpstreamException: {
#         "title": "Something went wrong",
#         "long_description": ["We experienced an unexpected error."],
#         "stage": "via",
#         "retryable": True,
#     },
#     UpstreamServiceError: {
#         "title": "Could not get web page",
#         "long_description": [
#             "Something went wrong when we tried to get the web page.",
#             "It might be missing or might have returned an error.",
#         ],
#         "stage": "upstream",
#         "retryable": True,
#     },
#     HTTPNotFound: {
#         "title": "Page not found",
#         "long_description": [
#             "The URL you asked for is not part of this service.",
#             "Please check the URL you have entered.",
#         ],
#         "stage": "request",
#         "retryable": False,
#     },
#     HTTPClientError: {
#         "title": "Bad request",
#         "long_description": [
#             "We can't process the request because we don't understand it."
#         ],
#         "stage": "request",
#         "retryable": False,
#     },
# }
# def _get_meta(exception):
# def google_drive_exceptions(exc, request):
# def _serialise_requests_info(request, response):
# def other_exceptions(exc, request):
# def _get_error_body(exc, request):
# def _set_status(exc, request):
# 
# Path: via/views/index.py
# class IndexViews:
#     def __init__(self, context, request):
#         self.context = context
#         self.request = request
#         self.enabled = request.registry.settings["enable_front_page"]
# 
#     @view_config(request_method="GET", renderer="via:templates/index.html.jinja2")
#     def get(self):
#         if not self.enabled:
#             return HTTPNotFound()
# 
#         self.request.response.headers["X-Robots-Tag"] = "all"
# 
#         return {}
# 
#     @view_config(request_method="POST")
#     def post(self):
#         if not self.enabled:
#             return HTTPNotFound()
# 
#         try:
#             url = self.context.url_from_query()
#         except HTTPBadRequest:
#             # If we don't get a URL redirect the user to the index page
#             return HTTPFound(self.request.route_url(route_name="index"))
# 
#         # In order to replicate the URL structure from original Via we need to
#         # create a path like this:
#         # http://via.host/http://proxied.site?query=1
#         # This means we need to pop off the query string and then add it
#         # separately from the URL, otherwise we'll get the query string encoded
#         # inside the URL portion of the path.
# 
#         # `context.url_from_query` protects us from parsing failing
#         parsed = urlparse(url)
#         url_without_query = parsed._replace(query="", fragment="").geturl()
# 
#         return HTTPFound(
#             self.request.route_url(
#                 route_name="proxy", url=url_without_query, _query=parsed.query
#             )
#         )


# Path: tests/unit/via/views/index_test.py
import pytest
from pyramid.httpexceptions import HTTPFound, HTTPNotFound
from tests.unit.matchers import temporary_redirect_to
from via.resources import QueryURLResource
from via.views.exceptions import BadURL
from via.views.index import IndexViews



class TestIndexViews:
    def test_get(self, views):
        assert views.get() == {}

    def test_post(self, views, pyramid_request):
        pyramid_request.params["url"] = "//site.org?q1=value1&q2=value2"

        redirect = views.post()

        assert isinstance(redirect, HTTPFound)
        assert (
            redirect.location
            == "http://example.com/https://site.org?q1=value1&q2=value2"
        )

    def test_post_with_no_url(self, views, pyramid_request):
        assert "url" not in pyramid_request.params

        redirect = views.post()

        assert redirect == temporary_redirect_to(
            pyramid_request.route_url(route_name="index")
        )

    def test_post_raises_if_url_invalid(self, views, pyramid_request):
        # Set a `url` that causes `urlparse` to throw.
        pyramid_request.params["url"] = "http://::12.34.56.78]/"


        with pytest.raises(BadURL):