Backend
Keep the frontend moving while the backend is not there yet
Agree on the API contract on day one, build against a fake API (a mock) and, once the backend is ready, change a single line. Here is a generator that runs in your browser, with no account and no limits, and a guide to deploying on virtech.
Three ways to mock an API
They are not exclusive: teams often start with the first and move to the second when the frontend needs a real server.
Fake data source
A Fake implementation of the interface the app uses. The fastest way to start the UI, and what your unit tests use.
json-server
A full API from a db.json: GET, POST, PUT, PATCH and DELETE, filters, pagination and relations. Changes are saved to the file. Works for the whole team and for phones.
Prism + OpenAPI
A mock that answers according to the contract and validates requests. Ideal for services between teams: the OpenAPI file is the agreement between both.
Generator
Describe your resources, get everything else
The data is generated in your browser and sent nowhere. The same schema always gives the same data, which is handy for tests.
One resource per line, not indented, with its fields below, indented: name: type. A ref links to another resource (stationId: ref stations).
idint 0-20number 0-40booltextnameemailaddresslatlngdatedatetimeenum A|Burlref resource
With Node.js installed, in the file's folder:
npx json-server@0.17.4 --watch db.json --port 8080 --host 0.0.0.0
You now have GET /stations, GET /stations/1, POST, PUT, PATCH and DELETE, filters (?status=IN_SERVICE, ?electric_gte=1), pagination (?_page=1&_limit=10) and relations (/stations/1/favorites, /favorites?_expand=station).
The contract, to share with the team that will consume your service. Open it in editor.swagger.io to browse it and, for a mock that validates requests:
npx @stoplight/prism-cli mock -h 0.0.0.0 -p 8080 openapi.yaml
In the data package of the Android project. The ViewModel receives a StationsDataSource: today you pass the Fake, tomorrow the one that calls the API with Retrofit.
In lib/data/ of the Flutter project. The BLoC gets a StationsDataSource from the locator (get_it or whatever you use).
From the mock to the real backend, changing one line
The key is that the UI does not know where the data comes from. It depends on an interface and, at start-up, the app decides which implementation to plug in.
// build.gradle.kts: buildConfigField("boolean", "USE_MOCK", "true") in the debug build
val dataModule = module {
single<StationsDataSource> {
if (BuildConfig.USE_MOCK) FakeStationsDataSource()
else HttpStationsDataSource(baseUrl = "http://10.0.2.2:8080/")
}
viewModel { StationsViewModel(get()) }
}
const useMock = bool.fromEnvironment('USE_MOCK', defaultValue: true);
const apiUrl = String.fromEnvironment('API_URL', defaultValue: 'http://10.0.2.2:8080');
void setupLocator() {
locator.registerLazySingleton<StationsDataSource>(
() => useMock ? FakeStationsDataSource() : HttpStationsDataSource(apiUrl),
);
}
// flutter run --dart-define=USE_MOCK=false --dart-define=API_URL=http://nattech.fib.upc.edu:40330
localhost is 10.0.2.2. The iOS simulator uses localhost. A real phone on the same Wi-Fi uses your computer's local IP (hence --host 0.0.0.0). Away from home, virtech.virtech, the FIB private cloud
A self-service virtual machine service for the courses that request it, at virtech.fib.upc.edu. Your teachers give you the accounts.
- Ubuntu machines with the
alumneuser, who can usesudo. You are responsible for everything that happens on them. - The course quota sets how many machines you get and how big they are. There is no firewall.
- There are no backups and machines are deleted at the end of the term. Code on GitHub; configuration documented.
- If you lose access to a machine, it cannot be recovered: delete it and create another. One more reason to script the installation.
FIB network only
Reachable from campus, or from home with the UPC VPN (UPClink). But the VPN is personal and allows a single connection: you cannot have your laptop and phone on it at once, nor give the app to anyone outside.
Template without VPN
It has 10 ports open to the Internet through nattech.fib.upc.edu, and SSH from UPC or over VPN. Any phone can reach it, stakeholders' phones included.
Create the machine and run your service
- VMs → +, pick the template, give it a name and the user password, then Create. Wait until it goes from DEPLOYING to RUNNING.
- Open the Console (VNC) and log in. The welcome message shows the IP and the ports. You can show it again with
/etc/update-motd.d/99-info-nat. - From then on, use SSH (from UPC or over VPN): work out the command below.
- Start the service listening on
0.0.0.0and on a port from 8080 to 8089. If it listens onlocalhost, it cannot be reached from outside. - Test it from outside with the public port:
http://nattech.fib.upc.edu:40330.
The one shown on virtech or in the welcome message.
How the ports are worked out
Every machine reaches the Internet through the same address, nattech.fib.upc.edu, and each one gets its own port range from the last number of its IP (172.16.4.XXX):
- SSH: port
22000 + XXX. - Services: from port
40000 + XXX·10onwards, ten consecutive ports mapped to 8080-8089 on the machine.
Install Node and keep the mock running
# Node.js 22
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
# from your computer (campus or VPN): upload db.json
ssh -p 22033 alumne@nattech.fib.upc.edu mkdir -p api
scp -P 22033 db.json alumne@nattech.fib.upc.edu:~/api/
# on the machine
cd ~/api && npm install json-server@0.17.4
npx json-server --watch db.json --port 8080 --host 0.0.0.0
To keep it running after you log out, turn it into a service:
# /etc/systemd/system/api.service
[Unit]
Description=API PES
After=network.target
[Service]
User=alumne
WorkingDirectory=/home/alumne/api
ExecStart=/home/alumne/api/node_modules/.bin/json-server --watch db.json --port 8080 --host 0.0.0.0
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload && sudo systemctl enable --now api
Your real backend works the same way: change ExecStart to the command that starts it.
How do I check the connection works before I have any service?
On the machine, nc -l -p 8080. On your computer, nc nattech.fib.upc.edu 40330 (with your port) and type anything: it should appear on the machine.
Why does ping not answer?
Because of how the NAT is set up, ping does not work from outside the machines' network, not even over VPN. Use curl or nc.
Can I SSH in from home without the VPN?
No. For security, SSH from outside UPC only works over the VPN. The 10 service ports are open to everyone.
I forgot the machine's password.
It cannot be recovered: delete the machine and create a new one. The virtech password (not the machine's) is changed in the user menu → Settings → Change password.
Mobile apps and unencrypted HTTP
nattech serves HTTP, not HTTPS. Android (since version 9) and iOS block that traffic by default, and the call fails with few clues. Allow it for this domain only.
<!-- res/xml/network_security_config.xml (in Flutter: android/app/src/main/res/xml/) -->
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="false">nattech.fib.upc.edu</domain>
<domain includeSubdomains="false">10.0.2.2</domain>
</domain-config>
</network-security-config>
<!-- AndroidManifest.xml -->
<application
android:networkSecurityConfig="@xml/network_security_config"
... >
<!-- ios/Runner/Info.plist -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>nattech.fib.upc.edu</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
Passwords travel in clear text over HTTP. For PES the per-domain exception is enough, but do not use real passwords and list it as a known limitation in the documentation.