aabhas
aabhas

Reputation: 416

Is it possible to check if a url sent to Flask will 404?

I have a list of urls and need to find all the ones that will not go to Flask's 404 not found page. Is there a way to check this?

Upvotes: 1

Views: 2327

Answers (3)

Caching
Caching

Reputation: 31

  1. What I try to test if the exact rule is existed in flask app.url_map:
"/the/exact/rule/<instance_id>" in [rule.rule for rule in app.url_map.iter_rules()]
  1. When testing the uri can be visited or not:
  • open with http connection (Browser, curl, httpie, postman etc)
  • using pytest:
@pytest.fixture
def client():
    from product.cli import app

    app.add_url_rule('/test/<instid>', 'test',
                     lambda instid: b'test_resp')
    with app.test_client() as client:
        yield client


def test_route_map(client):
    ret = client.get('/test/1')
    assert ret.data == b'test_resp'

Upvotes: 0

TheLetterN
TheLetterN

Reputation: 792

You can use the test_client method of app (or current_app if you're using blueprints) to create a temporary application context that you can send requests to and get flask.wrappers.Response instances back which contain response data, including the status_code of the response:

with current_app.test_client() as tc:
    resp = tc.get('/url/that/does/not/exist')

>>> resp.status_code
404

As such, to find all urls that return a 404 status, I would do:

# urls = list of strings containing URLs.

with current_app.test_client() as tc:
    not_found = [u for u in urls if tc.get(u).status_code == 404]

Upvotes: 0

davidism
davidism

Reputation: 127180

Use the underlying url map to simulate what would happen if Flask tried to dispatch each url as a request. This requires that the path, HTTP method (such as GET) and any query args are known and separate.

from werkzeug.routing import RequestRedirect, MethodNotAllowed, NotFound

to_test = (
    ('/user/1', 'GET', {}),
    ('/post/my-title/edit', 'POST', {}),
    ('/comments', 'GET', {'spam': 1}),
)
good = []
adapter = app.create_url_adapter(None)

if adapter is None:
    raise Exception('configure a SERVER_NAME for the app')

for path, method, args in to_test:
    try:
        adapter.match(path, method, query_args=args)
    except RequestRedirect:
        pass
    except (MethodNotAllowed, NotFound):
        continue

    good.append((path, method, args))

# good list now contains all tuples that didn't 404 or 405

This won't give the whole picture though, as the actual view could raise a 404 (or other error) during processing. Ultimately, you can't really know if a path is good unless you actually make a request to it.

Upvotes: 1

Related Questions