Quick Start
In under 5 minutes you will have an HTTP server running in VFP and responding to REST requests.
Prerequisites
- FoxServer installed and licensed
- VFP 9 SP2 or higher installed
- WinFx installed (visual project generator, optional but recommended)
1. Create the project
Open WinFx and create a new API project. This automatically generates the folder structure and configuration file.
Alternatively, manually create a .prg file with the controller:
2. Define the controller
The controller is a VFP class that inherits from ApiController. Each public method with a HELP comment is an endpoint:
* HelloController.prg
DEFINE CLASS HelloController AS ApiController OLEPUBLIC
PROCEDURE GetHello(req, res) HELP "GET: hello public"
LOCAL loResp
loResp = THIS.newObject("status,message")
loResp.status = "success"
loResp.message = "Hello from FoxServer!"
res.status(200).json(THIS.ToJson(loResp))
ENDPROC
PROCEDURE GetVersion(req, res) HELP "GET: hello/version public"
LOCAL loResp
loResp = THIS.newObject("version,server")
loResp.version = "1.0.0"
loResp.server = "FoxServer"
res.status(200).json(THIS.ToJson(loResp))
ENDPROC
ENDDEFINE | Element | Description |
|---|---|
ApiController | FoxServer base class — provides request, response and JSON utilities |
HELP "GET: hello public" | Declares the endpoint: HTTP method + route + visibility (public = no JWT) |
req | Object with all information about the incoming request |
res | Object to build and send the HTTP response |
THIS.newObject(fields) | Creates a dynamic VFP object with the indicated properties |
THIS.ToJson(obj) | Serializes a VFP object to a JSON string |
res.status(200).json(json) | Sends response with HTTP code 200 and JSON body |
3. Compile the project
Compile from WinFx or from VFP. The compiler generates an Interop DLL file that FoxServer loads.
4. Start the server
Start FoxServer pointing to your compiled project. If using Windows Service mode, see the Advanced Features section.
FoxServer.exe --project "C:\MiProyecto\config\myapi.json" 5. Test the endpoint
With the server running on port 8080, test from curl, Postman or the browser:
# GET /api/hello
curl http://localhost:8080/api/hello
# Response:
# {"status":"success","message":"Hello from FoxServer!"} Adding URL parameters
Parameters are declared in curly braces in the route and accessed via req.params:
PROCEDURE GetUser(req, res) HELP "GET: users/{id} public"
LOCAL lcId, loResp
lcId = req.params.id && "123" from /api/users/123
loResp = THIS.newObject("id,found")
loResp.id = lcId
loResp.found = .T.
res.status(200).json(THIS.ToJson(loResp))
ENDPROC curl http://localhost:8080/api/users/123
# {"id":"123","found":true} Reading the body (POST)
For POST requests with JSON body, access req.json:
PROCEDURE PostProduct(req, res) HELP "POST: products public"
LOCAL loBody, loResp
&& Body: {"name":"Widget","price":9.99}
IF ISNULL(req.json) OR EMPTY(req.json.name)
res.status(400).json('{"error":"name is required"}')
RETURN
ENDIF
loResp = THIS.newObject("status,name,price")
loResp.status = "created"
loResp.name = req.json.name
loResp.price = req.json.price
res.status(201).json(THIS.ToJson(loResp))
ENDPROC curl -X POST http://localhost:8080/api/products \
-H "Content-Type: application/json" \
-d '{"name":"Widget","price":9.99}'
# {"status":"created","name":"Widget","price":9.99}