Modern browsers hit preflight request to make sure if CORS (Cross Origin Resource Sharing) is being followed or not. This request brings details about the service which your client is looking forward to consume.
This detail includes allowed origins, allowed headers, allowed http methods etc. it’s browser’s responsibility to make this request if origin differs. If client is not allowed to access server resource this request will end up in HTTP Status code 401 and actual call will never be triggered by the browser. Worth to note that server has CORS mechanism configured and not client.
Note that it’s all about cross origin so if your server and client both belongs to same origin browser don’t need to make this preflight call.
To understand it more easily let’s take a simple example, you have an application which has client (Web Browser – i.e. AngularJS Application) running on localhost:1234 and server (Web Server – i.e. Java Web Application) is listening to localhost:4321 as these both belongs to different origin (even hosts are same ports differ in this case), when client tries to consume service of server it first fires OPTIONS request,
Access-Control-Request-Headers: origin, x-requested-with, Content-Type
If CORS has been configured appropriately to allow access to localhost:1234, it will return expected response,
HTTP/1.1 200 OK
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: origin, x-requested-with, Content-Type, Accept
Now, browser will check response including status, Access-Control-* headers etc. to make sure that what localhost:1234 is trying to do with localhost:4321 is allowed by the later one or not. As response is 200 and our client is in allowed origin also method which is going to be used in actual call is allowed.
CORS allow server to control accessibility of it’s resources from different origins. Servers like tomcat by default allow request from cross domains but you can override this setting in your application.