Home > Software engineering >  FastAPI and SlowAPI not working on Ajax and getJSON request - python
FastAPI and SlowAPI not working on Ajax and getJSON request - python

Time:02-19

I'm having a problem. When I make too many requests from browser or postman rightly the API (slowapi) blocks me as I have correctly set, but if I make a request via AJAX and jquery's $ .getJSON, the APIs don't block me. How can I solve? My code (extracted from the complete code):

from fastapi import FastAPI, Request, Response, status
from fastapi.middleware.cors import CORSMiddleware
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
from slowapi.middleware import SlowAPIMiddleware
limiter = Limiter(key_func=get_remote_address, default_limits=["2/5seconds"])
app = FastAPI()
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
app.add_middleware(SlowAPIMiddleware)

@app.get('/schools/{regione}/{provincia}/{comune}')
def search_school(request: Request, response: Response, regione: str, provincia: str, comune: str):
    if(request.headers.get("Provider") == "Test-User-Provider"):
        return {"message": "OK", "status": "success", "code": 200}

    else:
        response.status_code = status.HTTP_400_BAD_REQUEST
        return {"message": "Provider not found", "status": "error", "code": 400}

Browser result (WORK):

{"error":"Rate limit exceeded: 2 per 5 second"}

Jquery code (NOT WORK):

$.getJSON(apiURL "/schools/Test/Test/Test", function(data) {
        console.log(data)
});

Obviously with jquery I tried to make a lot of requests per second Console browser result (Not limited!):

{message: '...', status: 'success', code: 200}

Request not rate-limited

A thousand thanks.

UPDATE Through jquery I tried to make requests to other paths and it is correctly rate-limited. If I make the request to this path /schools/{region}/{province}/{municipality} the rate-limit does not work

UPDATE 2

I refer the updated and tested code. When I send a request to path /testpath /{region} it is correctly rate-limited. If instead I send a request to some sub-paths (/schools/{region}/{province}/{municipality} it is not rate-limited.

The jQuery code is the same as listed above

from fastapi import FastAPI, Request, Response, status
from fastapi.middleware.cors import CORSMiddleware
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
from slowapi.middleware import SlowAPIMiddleware

limiter = Limiter(key_func=get_remote_address, default_limits=["2/5seconds"])
app = FastAPI()
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

origins = ["http://127.0.0.1/", "http://localhost", "http://192.168.1.75"] ## CORS

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
app.add_middleware(SlowAPIMiddleware) ## Rate-limit all request

@app.get('/schools/{regione}/{provincia}/{comune}')
def search_school(request: Request, response: Response, regione: str, provincia: str, comune: str):
        return {"message": 'No schools found!', "status": 'error', "code": 200} ## Or if found return schools informations

@app.get('/testpath/{regione}') ## Works with one path. If I add "provincia" and "comune" non work
def search_school(request: Request, response: Response, regione: str, provincia: str, comune: str):
        return {"message": 'No schools found!', "status": 'error', "code": 200} ## Or if found return schools informations

If i use schools path: enter image description here

If i use testpath it's correct rate-limited: enter image description here

CodePudding user response:

Tested your code and works fine, as long as you replace the closing double quote with a straight double quote " in the getJSON() method:

$.getJSON(apiURL   "/security/validate_token", function(data) {
        console.log(data)
});

Above you wrote "the status response is personalized and I decided it myself". So, if you still get a {message: '...', status: 'success', code: 200} response, I would suggest you try returning a simple message instead, e.g., return {"status": "success"}, and see if that works as expected. If not, it might be something not implemented in the right way in your custom response.

Update

The below should work as expected. If it doesn't, then the issue likely lies elsewhere in code that is not inlcuded in your question. I would also suggest to add it as a tempalte to your app, as from the error you posted you seem to be getting Cross-Origin warnings.

<!DOCTYPE html>
<html>
   <head>
      <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
      <script type="text/javascript" >
         function on_click(){
            $.getJSON("http://127.0.0.1:8000/schools/Test/Test/Test", function(data) {
                 console.log(data)
            });
         }
      </script>
   </head>
   <body>
      <input type="button" value="submit" onclick="on_click()">
   </body>
</html>
  • Related