4D Blog

Home Product Master HTTP Requests with 4D Request Handlers

Master HTTP Requests with 4D Request Handlers

February 10, 2025

Product

In today’s web-driven world, servers process an overwhelming number of requests. Efficiently analyzing, counting, interpreting, and rerouting these requests is essential, especially when applying MVC principles.

In 4D 20 R8, with the introduction of HTTP Request Handlers on the 4D HTTP Server, you can define accurately which business logic you want to trigger regarding specific URLs patterns.

Main advantages of this feature are:

  • Offering more granularity in implementing the code handling received requests. This business logic can be split in several classes. Forget extensive Case of statements in the On Web Connection database method.
  • Allowing a redirection on a Qodly page which opens up new perspectives to extend 4D application on the web

 

This powerful feature unlocks many possibilities, as detailed below. Keep reading to learn more and work with concrete examples.

HDI_HTTP_RequestHandler

Before diving into details, let’s have a comparative analysis showing all the benefit you can take from this feature.

comparative analysis

Can I: Using on Web Connection database method as a handler Using HTTP Handlers
Split my code handling requests among several classes No Yes
Redirect the user on a Qodly page No Yes
Force a user to authenticate themselves even when requesting an existing web resource (e.g. an existing html page) No Yes

To illustrate that, let’s have a look at those simple requirements:

  • As long as the user is not authenticated, they must be redirected on an authentication page.
  • They can only view the html pages in the /pages folder. If they request an unexisting page in this folder, they are redirected on a Not found page.
  • If they request other resources, they are redirected on a Not authorized page.
  • The /pages request displays the /pages/welcome.html page.
  • The authorized html pages offer some upload and download files features

 

how to do that with the On Web Authentication / Connection database methods

The On Web Authentication method

Case of 
	// The user is not authenticated	
	: (Session.isGuest())
		WEB SEND HTTP REDIRECT("/authentication/authentication.html")
		return False
	Else 
		return True
End case

The On Web connection method

#DECLARE($url : Text)

Case of 
		
	: ($url="/pages")
		WEB SEND HTTP REDIRECT("/pages/welcome.html")
		
	: (Position("/fileUpload/"; $url)=1)
		//Handle the file upload business logic
		
	: (Position("/fileDownload"; $url)=1)
		//Handle the file download business logic
		
        // The requested resource is not an html page of the pages folder
	: Not(Match regex("/pages/[a-z]*[0-9]*[.]html"; $url))
		WEB SEND HTTP REDIRECT("/error/notAuthorized.html")
	Else 
		WEB SEND HTTP REDIRECT("/error/notFound.html")
End case 

It is just a sample of code showing the On Web Connection database method might be complex, thus difficult to maintain.

with The http request handlers

The series of examples below will show you how to easily associate some URL patterns to specific business logic and how to organize properly this code among classes.

You’ll also learn how to handle a redirection on Qodly pages and how to redirect the user on an authentication page (even when requesting an existing resource).

request handlers why?

Handling request handlers leads to various scenarios such as:

  • use a given URL as a resource provider (e.g., download various files by calling a specific URL)
  • use a given URL as a file-uploading box (e.g., upload various files by calling a specific URL)
  • handle redirection on specific pages according to a business context (e.g., user authenticated or not, not found page, privileges granted or not … et.c)

how to set up an HTTP request handler

The HTTP request handlers must be set up in the HTTPHandlers.json file in the Project/Sources folder.

This file contains a JSON format collection of objects. Each object refers a request handler with the following information:

  • the URL pattern to handle
  • the verb used by the URL
  • the [singleton class + function] where the request handler code is implemented

 

example

HTTPHandlers.json file:

[
    {
        "class": "GeneralHandling",
        "method": "gettingStarted",
        "pattern": "start",
        "verbs": "get, post"
    }
]

Question: What does it mean?

Answer: This means that when any request starting by /start/ with a GET or POST verb is received on the server, the function gettingStarted of the singleton GeneralHandling is executed.

how to implement the request handler code

The singleton class mentioned above must be shared.

Input: an instance of the 4D.IncomingMessage class

The request is received on the server as an object instance of the 4D.IncomingMessage class.

The following information is available:

  • the complete url of the request
  • the parts of the url
  • the verb of the request
  • the headers of the request
  • the parameters put in the URL (if any)
  • the body of the request (if any)

 

Then, the request handler can use all this information to trigger appropriate business logic.

Output: an instance of the 4D.OutgoingMessage class

If needed, the request handler can return an object instance of the 4D.OutgoingMessage class, i.e. some full web content ready for a browser to handle (e.g. such as file content).

a simple example to start

With the same HTTPHandlers.json file as above:

[
    {
        "class": "GeneralHandling",
        "method": "gettingStarted",
        "pattern": "start",
        "verbs": "get, post"
    }
]

The request http://127.0.0.1/start/example?param=demo&name=4D is run with a GET verb in a browser. It is handled by the gettingStarted() function of GeneralHandling singleton class below:

shared singleton Class constructor()


Function gettingStarted($request : 4D.IncomingMessage) : 4D.OutgoingMessage

var $result:=4D.OutgoingMessage.new()
var $body : Text

$body:="Called URL: "+$request.url+"\n"

$body+="The parameters are received as an object:"+"\n"+JSON Stringify($request.urlQuery; *)+"\n"

$body+="The verb is: "+$request.verb+"\n"

$body+="There are "+String($request.urlPath.length)+" url parts - Url parts are: "+$request.urlPath.join(" - ")+"\n"+"\n"

$result.setBody($body)
$result.setHeader("Content-Type"; "text/plain")

return $result

The request is received on the server as $request (an object instance of the 4D.IncomingMessage class).

This $request object contains the properties:

  • url (String) – URL of the request
  • urlQuery (Object) – Parameters of the request.
  • verb (String) – Verb
  • urlPath (collection of Strings) – URL parts of the request

 

Here is the response:

how to handle a body in the request

The 4D.IncomingMessage class provides some functions to get the headers and the body of the request.

example

Let’s run a simple example to upload a file on the server.

The HTTPHandlers.json file:

[
    {
        "class": "UploadFile",
        "method": "uploadFile",
        "regexPattern": "/putFile",
        "verbs": "POST"
    }
]

Note that the URL pattern is given as a regular expression with the regexPattern property.

The request http://127.0.0.1:8044/putFile?fileName=testFile is run with a POST verb and a file content in its body.

The UploadFile singleton class:

Function uploadFile($request : 4D.IncomingMessage) : 4D.OutgoingMessage
	
var $response:=4D.OutgoingMessage.new()
var $body:="Not supported file"
var $fileName; $fileType : Text
var $file : 4D.File
var $picture : Picture
var $created : Boolean
	
//The file name is given as parameter in the URL
$fileName:=$request.urlQuery.fileName
	
// The header "Content-Type" provides the format of the body
$fileType:=$request.getHeader("Content-Type")
	
Case of 
	// The body contains a pdf file
	: ($fileType="application/pdf")
		$file:=File("/PACKAGE/Files/"+$fileName+".pdf")
		$created:=$file.create()
		// The getBlob() function returns the body of the request as a Blob
		$file.setContent($request.getBlob())
		$body:="Upload OK - File size: "+String($file.size)
			
	// The body contains a jpg image
	: ($fileType="image/jpeg")
		$file:=File("/PACKAGE/Files/"+$fileName+".jpg")
		// The getPicture() function returns the body of the request as a Picture
		$picture:=$request.getPicture()
		WRITE PICTURE FILE($file.platformPath; $picture)
		$body:="Upload OK - Image size: "+String($file.size)
End case 

$response.setBody($body)
$response.setHeader("Content-Type"; "TEXT/plain")
	
return $response

The file name is given as parameter (fileName) in the URL. It is received in the urlQuery object in the request.

Functions to get the headers and the body of the request

In the example above, note the getHeader() function which returns a given header of the request. The 4D.IncomingMessage class also offers a headers property (Object) containing all the request headers.

The header Content-Type provides the format of the received body. In this example, only the pdf and jpeg formats are handled.

Note the getBlob() and getPicture() functions on the $request object. They provide the body content in the appropriate format that matches the Content-Type header.

See the documentation for more details about those functions.

A getText() function is also available and provides the body of the request as a String (if it has been sent as a String)

If the body has been given as a valid JSON representation, the getJSON() function provides its resolution with the correct type (e.g. , Object, Collection, String, …). 

handle redirection

The request handler is also able to redirect on a specific page by returning an instance of the the 4D.OutgoingMessage class. The Location header must be used to indicate the page to redirect on.

The HTTP status 3xx value indicates the client must take additional action to complete the request.

Let’s run this scenario:

– The user can view all the html pages in the WebFolder/pages folder once they are authenticated. As long as the user is not authenticated, they are redirected on an authentication page.

– If the asked page is not in this folder, a Not found page is served.

– If the user asks for a page in a subfolder of the /pages folder, a Not authorized page is served.

The HTTPHandlers.json file:

[
    {
        "class": "PagesHandling",
        "method": "handle",
        "regexPattern": "/pages/"
    }
]

The PagesHandling singleton class:

shared singleton Class constructor()
	
Function handle($request : 4D.IncomingMessage) : 4D.OutgoingMessage
	
var $result:=4D.OutgoingMessage.new()
var $file : 4D.File
	
//The user is not authenticated
If (Session.isGuest())
	$result.setHeader("Location"; "/authentication/Authentication.html")
	$result.setStatus(307)
Else 
		
	//The URL is an html page in the /pages folder
	If (($request.urlPath.length=2) && (Position(".html"; $request.url)#0))
			
		$file:=File("/PACKAGE/WebFolder"+$request.url)
			
		//The pages exists
		If ($file.exists)
			$result.setBody($file.getContent())
			$result.setHeader("Content-Type"; "text/html")
			$result.setStatus(200)
				
		//The pages does not exist
		Else 
			$result.setHeader("Location"; "/error/NotFound.html")
			$result.setStatus(307)
		End if 
			
	//The URL is NOT a an html page in the /pages folder
	Else 
		$result.setHeader("Location"; "/error/NotAuthorized.html")
		$result.setStatus(307)
	End if 
End if 
	
return $result

Note that the request handler has access to the Session object which allows more complex business logic (checking the presence of some privileges, use the Session.storage shared object). 

Compare this example with the example given at the top of this blogpost (redirection handled with the On Web Connection database method). You’ll see that thanks to the URL patterns given in the HTTPHandlers.json file and the urlPath property of the 4D.IncomingMessage class, no need to test complex regex for the URL.

how to redirect on a qodly page?

Just indicate the rendering URL of your Qodly page in the Location header.

$result.setHeader("Location"; "https://myQodlyApp/$lib/renderer/?w=Authentication")

Download the HDI to practise handling the HTTP requests and don’t wait more to enter the project mode world proposing classes and other powerful features. 

Discuss

Tags 20 R8, 4D server, HTTP, HTTP Request handler, Request

Latest related posts

  • June 16, 2025

    Generate, share and use web sessions One-Time Passcodes (OTP)

  • May 20, 2025

    Automatic Refresh of OEM Build Licenses

  • May 16, 2025

    New class to handle incoming TCP connections

Avatar
Marie-Sophie Landrieu-Yvert
• Product Owner • Marie-Sophie Landrieu-Yvert has joined the 4D Product team as a Product Owner in 2017. As a Product Owner, she is in charge of writing the user stories then translating it to functional specifications. Her role is also to make sure that the feature implementation delivered is meeting the customer need.Marie-Sophie graduated from the ESIGELEC Engineering School and began her career as an engineer at IBM in 1995. She participated on various projects (maintenance or build projects) and worked as a Cobol developer. Then she worked as an UML designer and Java developer. Lately her main roles were analyzing and writing functional requirements, coordinate business and development teams.
  • Deutsch
  • Français
  • English
  • Português
  • Čeština
  • Español
  • Italiano
  • 日本語

Categories

Browse categories

  • 4D View Pro
  • 4D Write Pro
  • 4D for Mobile
  • Email
  • Development Mode
  • 4D Language
  • ORDA
  • User Interface / GUI
  • Qodly Studio
  • Server
  • Maintenance
  • Deployment
  • 4D Tutorials
  • Generic
  • 4D Summit sessions and other online videos

Tags

4D-Analyzer 4D for Android 4D for iOS 4D NetKit 4D Qodly Pro 4D View Pro 4D Write Pro 20 R8 20 R9 Administration Authentication Build application CI/CD Class Client/Server Code editor Collections Compatibility settings Formula Listbox Logs Mail Microsoft 365 Network Objects ORDA PDF Pictures Preemptive Programming Qodly Studio REST Scalability Security Session Source control Speed Spreadsheet Tutorial UI User Experience v20 vscode Web Word processor

Tags

4D-Analyzer 4D for Android 4D for iOS 4D NetKit 4D Qodly Pro 4D View Pro 4D Write Pro 20 R8 20 R9 Administration Authentication Build application CI/CD Class Client/Server Code editor Collections Compatibility settings Formula Listbox Logs Mail Microsoft 365 Network Objects ORDA PDF Pictures Preemptive Programming Qodly Studio REST Scalability Security Session Source control Speed Spreadsheet Tutorial UI User Experience v20 vscode Web Word processor
Subscribe to 4D Newsletter

© 2025 4D SAS - All rights reserved
Terms & Conditions | Legal Notices | Data Policy | Cookie Policy | Contact us | Write for us


Subscribe to 4D Newsletter

* Your privacy is very important to us. Please click here to view our Policy

Contact us

Got a question, suggestion or just want to get in touch with the 4D bloggers? Drop us a line!

* Your privacy is very important to us. Please click here to view our Policy