What is RPC (Remote Procedure Call)?
How RPC Works (Step-by-Step)
Difference Between REST and RPC (JSON-RPC, gRPC)
Programmatical advantage on RPC
How to implement RPC on LARAVEL
RPC (Remote Procedure Call)?
Remote Procedure Call (RPC) is a mechanism that allows programs to call functions/methods on a remote server as if they were local.
π Think of it as calling a function in another program running on a different machine. The RPC framework handles:
Data serialization (convert data into a format for transmission)
.
Network transport (send and receive requests over TCP, HTTP, etc.)
.
Request handling (execute function calls remotely)
.
How RPC Works (Step-by-Step)
1οΈβ£ Client Calls a Function
The client program calls a method (getUserDetails()).
2οΈβ£ RPC Framework Serializes Data
Converts the method name & parameters into JSON, Protobuf, or XML.
3οΈβ£ Request Sent to Server
Over HTTP, TCP, or WebSockets.
4οΈβ£ Server Processes the Request
Server receives, deserializes data, and executes getUserDetails().
5οΈβ£ Server Sends the Response
The response (user details) is sent back.
6οΈβ£ Client Receives & Deserializes Response
The response is converted back into a usable object.
Difference Between REST and RPC (JSON-RPC, gRPC)
1οΈβ£ What is REST API?
Uses HTTP methods (GET, POST, PUT, DELETE) with URLs.
Each resource has a specific endpoint (/users, /updatePassword).
Stateless (Each request is independent).
Best for public APIs (Easy to cache, debug).
β
Example: REST API
πΉ Server (Node.js + Express)
const express = require("express");
const app = express();
app.use(express.json());
app.post("/updatePassword", (req, res) => {
const { email, password } = req.body;
console.log(`Updating password for ${email}`);
res.json({ success: true, message: "Password updated" });
});
app.listen(3000, () => console.log("REST API running on port 3000"));
πΉ Client (Flutter - Dart)
import 'dart:convert';
import 'package:http/http.dart' as http;
class MotoshareAPI {
String baseUrl = "http://localhost:3000";
Future<void> updatePassword(String email, String password) async {
var body = jsonEncode({"email": email, "password": password});
final response = await http.post(
Uri.parse("$baseUrl/updatePassword"),
headers: {"Content-Type": "application/json"},
body: body,
);
print("Response: ${response.body}");
}
}
β Calls POST /updatePassword with JSON body.
What is JSON-RPC?
Remote Procedure Call (RPC): Calls a method (updatePassword) remotely.
Uses structured JSON requests instead of URLs.
Single API endpoint (/rpc) handles multiple methods.
Best for microservices, Web3, or private APIs.
Server (Python + Flask + JSON-RPC)
from flask import Flask, request, jsonify
from jsonrpcserver import method, dispatch
app = Flask(__name__)
@method
def updatePassword(email: str, password: str):
print(f"Updating password for {email}")
return {"success": True, "message": "Password updated"}
@app.route("/rpc", methods=["POST"])
def rpc():
return jsonify(dispatch(request.get_data().decode())), 200
if __name__ == "__main__":
app.run(port=5000)
πΉ Client (Flutter - Dart)
import 'dart:convert';
import 'package:http/http.dart' as http;
class MotoshareAPI {
String baseUrl = "http://localhost:5000/rpc"; // Single JSON-RPC endpoint
Future<void> updatePassword(String email, String password) async {
var body = jsonEncode({
"jsonrpc": "2.0",
"method": "updatePassword",
"params": { "email": email, "password": password },
"id": 1
});
final response = await http.post(
Uri.parse(baseUrl),
headers: {"Content-Type": "application/json"},
body: body,
);
print("Response: ${response.body}");
}
}
Advantages of RPC over REST API
1οΈβ£ Simplicity in Calling Methods
πΉ RPC: You call remote methods as if they were local functions.
πΉ REST: You need to structure URLs, methods (GET, POST, PUT, DELETE), and handle HTTP responses.
Example:
β
RPC Call (JSON-RPC)
{
"jsonrpc": "2.0",
"method": "updatePassword",
"params": { "email": "user@example.com", "password": "newPass123" },
"id": 1
}
β
REST API Call
{
"email": "user@example.com",
"password": "newPass123"
}
But in REST, you also need:
Correct HTTP Method: (POST /updatePassword)
Headers: (Content-Type: application/json)
URL Encoding (for GET queries)
More Efficient Data Transfer (Especially with gRPC)
πΉ RPC (gRPC) uses binary Protocol Buffers (Protobuf), making it much faster than RESTβs JSON.
πΉ REST uses HTTP 1.1 and JSON, which is slower due to text-based communication.
Programmatical advantage on RPC
Setting Up Laravel Backend (Server-Side)
We'll create a Laravel API that supports both JSON-RPC and REST API.
π Step 1: Install Laravel
composer create-project --prefer-dist laravel/laravel motosharerpc
cd motosharerpc
π Step 2: Set Up Routes in routes/api.php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserController;
// REST API Route
Route::put('/updatePassword', [UserController::class, 'updatePassword']);
// JSON-RPC Route
Route::post('/rpc', [UserController::class, 'handleRpc']);
π Step 3: Create UserController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class UserController extends Controller
{
// π REST API Method
public function updatePassword(Request $request)
{
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'password' => 'required|min:6'
]);
if ($validator->fails()) {
return response()->json(['error' => $validator->errors()], 400);
}
$user = User::where('email', $request->email)->first();
if (!$user) {
return response()->json(['error' => 'User not found'], 404);
}
$user->password = Hash::make($request->password);
$user->save();
return response()->json(['message' => 'Password updated successfully']);
}
// π JSON-RPC Method
public function handleRpc(Request $request)
{
$data = $request->json()->all();
if (!isset($data['method']) || $data['method'] !== 'updatePassword') {
return response()->json([
'jsonrpc' => '2.0',
'error' => ['code' => -32601, 'message' => 'Method not found'],
'id' => $data['id'] ?? null
]);
}
$params = $data['params'];
$validator = Validator::make($params, [
'email' => 'required|email',
'password' => 'required|min:6'
]);
if ($validator->fails()) {
return response()->json([
'jsonrpc' => '2.0',
'error' => ['code' => -32602, 'message' => 'Invalid params'],
'id' => $data['id']
]);
}
$user = User::where('email', $params['email'])->first();
if (!$user) {
return response()->json([
'jsonrpc' => '2.0',
'error' => ['code' => -32602, 'message' => 'User not found'],
'id' => $data['id']
]);
}
$user->password = Hash::make($params['password']);
$user->save();
return response()->json([
'jsonrpc' => '2.0',
'result' => 'Password updated successfully',
'id' => $data['id']
]);
}
}
π οΈ 2οΈβ£ Flutter Frontend Implementation
We'll build a simple Flutter App that allows the user to update their password using both JSON-RPC and REST API.
π Step 1: Add Dependencies to pubspec.yaml
dependencies:
flutter:
sdk: flutter
http: ^0.13.3
π Step 2: Create network_service.dart
This file will handle API requests.
import 'dart:convert';
import 'package:http/http.dart' as http;
class NetworkService {
final String baseUrl = "http://10.0.2.2:8000/api"; // Local Laravel Server
// π REST API Call
Future<Map<String, dynamic>> updatePasswordRest(String email, String password) async {
final response = await http.put(
Uri.parse("$baseUrl/updatePassword"),
headers: {"Content-Type": "application/json"},
body: jsonEncode({"email": email, "password": password}),
);
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception("Failed to update password");
}
}
// π JSON-RPC Call
Future<Map<String, dynamic>> updatePasswordJsonRpc(String email, String password) async {
final response = await http.post(
Uri.parse("$baseUrl/rpc"),
headers: {"Content-Type": "application/json"},
body: jsonEncode({
"jsonrpc": "2.0",
"method": "updatePassword",
"params": {"email": email, "password": password},
"id": 1
}),
);
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception("JSON-RPC request failed");
}
}
}
π Step 3: Create main.dart (Flutter UI)
import 'package:flutter/material.dart';
import 'network_service.dart';
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: PasswordUpdateScreen(),
));
}
class PasswordUpdateScreen extends StatefulWidget {
@override
_PasswordUpdateScreenState createState() => _PasswordUpdateScreenState();
}
class _PasswordUpdateScreenState extends State<PasswordUpdateScreen> {
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
final NetworkService _networkService = NetworkService();
String responseMessage = "";
Future<void> updatePassword(bool useJsonRpc) async {
try {
final email = emailController.text;
final password = passwordController.text;
Map<String, dynamic> response;
if (useJsonRpc) {
response = await _networkService.updatePasswordJsonRpc(email, password);
} else {
response = await _networkService.updatePasswordRest(email, password);
}
setState(() {
responseMessage = response.containsKey('result') ? response['result'] : response['message'];
});
} catch (e) {
setState(() {
responseMessage = "Error: $e";
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Update Password")),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
controller: emailController,
decoration: InputDecoration(labelText: "Email"),
),
TextField(
controller: passwordController,
decoration: InputDecoration(labelText: "New Password"),
obscureText: true,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () => updatePassword(false),
child: Text("Update via REST API"),
),
ElevatedButton(
onPressed: () => updatePassword(true),
child: Text("Update via JSON-RPC"),
),
SizedBox(height: 20),
Text(responseMessage, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
],
),
),
);
}
}
JSON-RPC Request Example (Calling updatePassword)
{
"jsonrpc": "2.0",
"method": "updatePassword",
"params": { "email": "user@example.com", "password": "newPass123" },
"id": 1
}
REST API Request Example (updatePassword)
{
"email": "user@example.com",
"password": "newPass123"
}
Top comments (0)