Controllers within Odoo 19 manage HTTP requests and the corresponding responses that are generated by the server for those requests. In other words, controllers are a means for clients (such as browsers, mobile applications, or third-party services) to communicate with the Odoo server and receive web pages, RESTful web services, or other types of responses from the Odoo server.
A controller defines the route (URL) that a client will call, and it decides how to process the request based on which HTTP method (GET, POST, PUT, DELETE) was used for the request. Because of this, Odoo 19 controllers can handle all types of websites, including simple ones and complex ones that require business logic integration via an API.
Here’s a basic example of a controller in Odoo:
from odoo import http
class MyFirstController(http.Controller):
@http.route('/hello', type='http', auth='public', website=True)
def hello_world(self, **kwargs):
return "Hello, welcome to Odoo 19!"
/hello is the route (URL) that users can visit.
type='http' specifies that it returns a standard HTTP response.
auth='public' allows anyone (even without logging in) to access it.
website=True makes it available on the website frontend.
The method simply returns a plain text response.
Types of Requests in Odoo 19
In Odoo 19, controllers mainly handle two categories of requests:
- HTTP Requests (GET, POST)
- JSONRPC Requests (commonly used for APIs)
a) HTTP Requests
Most of the time, HTTP requests are used to send and receive information between Odoo and clients. Two common types of HTTP requests are GET and POST, which have specific use cases.
The GET method is the type of request sent by clients when they want to retrieve information from a resource, such as a webpage displaying customer details. Clients use this type of request to access information stored at the resource's URL.
The POST method is the request type sent by clients to submit information to the server. Clients use this method when creating new records in the database or sending completed forms to the server.
HTTP requests play an important role in normal website interaction, including displaying web pages, processing forms, and serving static files and images.
Example of GET and POST Methods:
from odoo import http
class MyController(http.Controller):
@http.route('/get_example', type='http', auth='public', methods=['GET'])
def get_method(self, **kw):
return "This is a GET request!"
@http.route('/post_example', type='http', auth='public', methods=['POST'])
def post_method(self, **kw):
return "This is a POST request!"
In this case, the /get_example route is set up to respond to a GET request, whereas the /post_example route is designed to process a POST request.
b) JSON-RPC Requests
The use of JSONRPC requests is primarily for API style interaction with Odoo 19, where they enable the client to send structured data (JSON formatted) to the server and the server responds with structured data. As such, they are well-suited for creating interfaces between third-party applications, mobile applications, or custom services that require programmatic data exchange.
Example of a JSONRPC request:
from odoo import http
class MyJsonrpcController(http.Controller):
@http.route('/jsonrpc_example',type='jsonrpc', auth='public')
def jsonrpc_method(self, **kw):
return {"message": "This is a JSONRPC response!"}
When a client makes a request to the /jsonrpc_example route, the server replies with a JSONRPC object: {"message": "This is a JSONRPC response!"}.
Key Parameters in an Odoo 19 Request
The following are the essential parameters that will be passed to the Odoo controller along with the request.
a) cr (Cursor)
Cr (Cursor) is used by developers to execute low-level SQL queries directly against Odoo's database (the server). Although Odoo provides developers the ability to use Models rather than direct SQL queries, the cr parameter is utilized if you need to execute direct SQL queries.
b) Context
The context parameter provides access to additional information related to the request, such as the active user, language settings or any extra information specific to the request. Odoo uses the context parameter to ensure that the requested actions are valid for the request context (e.g. translations, permissions, default values).
c) Env
Env provides developers direct access to Odoo's ORM. With env, developers can easily manipulate the database using the Odoo Object Model (e.g. by creating a partner, updating an order, or searching for records) without needing to write any SQL.
Example using env to retrieve records:
from odoo import http
class MyController(http.Controller):
@http.route('/customers', auth='user', type='http')
def get_customers(self, **kw):
customers = http.request.env['res.partner'].search([])
return f"Found {len(customers)} customers!"
In this example, the env object is used to fetch all customer records from the res.partner model.
d) sessions
The user session object will track the user session during an HTTP request, including information about whether the user is logged in, the user’s authentication information, and all transactions that are open. The session object also allows a single user to send multiple requests without losing continuity.
Security in Requests (CSRF Token
Odoo 19 comes with an anti-CSRF method called csrf_token() designed to mitigate the risks associated with Cross-Site Request Forgery (CSRF). The csrf_token() method creates a unique token that must accompany certain requests, thereby verifying that the request originates from an authentic user session rather than a rogue agent.
Example of using CSRF protection:
from odoo import http
from odoo.http import request
class MyController(http.Controller):
@http.route('/secure', auth='user', methods=['POST'], csrf=True)
def secure_route(self, **kw):
csrf_token = request.csrf_token()
return f"CSRF token: {csrf_token}"
In this case, the /secure route creates a CSRF token and checks it when handling a POST request.
Handling Responses
In Odoo 19, different types of controller responses may be issued depending on the circumstance. You can use either the make_response() function or create a new response object using the Response class to return custom responses.
a)The make_response()
This function allows you to create your own HTTP response by specifying the content, setting cookies and headers, etc., giving you greater flexibility when sending responses to clients.
Example of a custom response:
from odoo import http
from odoo.http import request
class MyController(http.Controller):
@http.route('/custom_response', auth='public')
def custom_response(self, **kw):
response_data = "This is a custom response!"
headers = {'Content-Type': 'text/plain'}
return request.make_response(response_data, headers=headers)
In this case, the make_response() function is used to return a plain text message along with specific custom headers.
b) The Response Class
When creating an HTTP response, the Response class allows for more variation. It allows the user to choose how to create the response's body and headers, set status codes, manage cookies, etc.
Example using Response:
from odoo import http
from odoo.http import Response
class MyController(http.Controller):
@http.route('/response_class', auth='public')
def response_class_method(self, **kw):
return Response("This is a response using the Response class", status=200)
This method returns a response with a 200 status code.
Error Handling in HTTP Requests
When developing with HTTP APIs for version 19 of the Odoo application, it is critical to handle potential error conditions gracefully. Common examples of this would include receiving back a "404 Not Found" message when a requested resource does not exist, or a "500 Internal Server Error" message if an unexpected error occurs on the server side.
Example of handling errors:
from odoo import http
from odoo.http import Response
class MyController(http.Controller):
@http.route('/error_example', auth='public')
def error_handling(self, **kw):
try:
# Attempt to fetch data (this could fail)
data = http.request.env['some.model'].search([('id', '=', 1)])
if not data:
return Response("Resource not found", status=404)
return f"Found record: {data.name}"
except Exception as e:
return Response(f"Internal Server Error: {str(e)}", status=500)
In the above-mentioned instance, if a user requests a record that does not exist, Odoo would generate a 404 Not Found response to indicate this issue. Conversely, if there was an unexpected error, Odoo would provide a response of 500 Internal Server Error.
JSONRPC Requests with Error Handling
When developers are working with JSONRPC requests made to Odoo version 19, it is also very important that developers handle any potential errors correctly so the client ends up with both clear and structured responses.
Example of a JSONRPC request with error handling:
Request:
{
"jsonrpc": "2.0",
"method": "call",
"params": {"context": {}, "arg1": "value1"},
"id": null
}
Successful Response:
{
"jsonrpc": "2.0",
"result": {"res1": "value1"},
"id": null
}
The Response to the request producing an error will be:
{
"jsonrpc": "2.0",
"error": {
"code": 1,
"message": "Error occurred",
"data": {
“code”: “codestring”,
"debug": "traceback"}
},
"id": null
}Conclusion
Controllers within Odoo version 19 are critical to process client requests, generate tailored responses based on the nature of those requests, and handle the results from those responses. By understanding how to work with both HTTP request handling as well as JSONRPC request handling, by utilizing some of the most important controller parameters (cr, context, env) and also utilizing Odoo's make_response() method or Response class, developers can create secure, flexible, and efficient web services (APIs). All of these abilities will allow developers to build dynamic and interactive applications directly inside the Odoo framework, allowing for both increased functionality and user experience.
To read more about Key Elements of Controller Request & Response in Odoo 18, refer to our blog Key Elements of Controller Request & Response in Odoo 18