Overview
In this guide, we'll show you how to build and deploy a webhook service for receiving data from QuickNode Streams using various programming languages. Whether you're using Node.js, Python, Ruby, PHP, Java, Go, Rust, we've got you covered with step-by-step instructions.
With these examples, you can set up a webhook server in your preferred language, install the necessary dependencies, run the server, and expose it to the internet using ngrok. This will enable you to start receiving data from QuickNode Streams seamlessly.
What You Will Need
- Basic understanding of QuickNode Streams
- A QuickNode Account - (Sign Up here)
Table of Contents
Node.js
Setup Environment and Install Dependencies
mkdir nodejs-webhook
cd nodejs-webhook
npm init -y
Create server.js
const http = require('http');
const server = http.createServer((req, res) => {
if (req.method === 'POST' && req.url === '/webhook') {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
console.log('Received webhook. Request details:');
console.log('Headers:', JSON.stringify(req.headers, null, 2));
try {
const jsonData = JSON.parse(body);
console.log('Parsed JSON data:');
console.log(JSON.stringify(jsonData, null, 2));
} catch (error) {
console.log('Error parsing JSON:', error.message);
console.log('Raw body:', body);
}
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Webhook received');
});
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 Not Found');
}
});
const PORT = 3000;
server.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Run the webhook
node server.js
Expose to the Internet
Use ngrok:
ngrok http 3000
Go
Setup Environment and Install Dependencies
mkdir go-webhook
cd go-webhook
Create main.go
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
func webhookHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
fmt.Println("Received webhook. Request details:")
headers, _ := json.MarshalIndent(r.Header, "", " ")
fmt.Printf("Headers: %s\n", headers)
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Error reading body", http.StatusInternalServerError)
return
}
var jsonData interface{}
if err := json.Unmarshal(body, &jsonData); err != nil {
fmt.Println("Error parsing JSON:", err)
fmt.Println("Raw body:", string(body))
} else {
fmt.Println("Parsed JSON data:")
prettyJSON, _ := json.MarshalIndent(jsonData, "", " ")
fmt.Println(string(prettyJSON))
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("Webhook received"))
}
func main() {
http.HandleFunc("/webhook", webhookHandler)
fmt.Println("Server is running on port 3000")
log.Fatal(http.ListenAndServe(":3000", nil))
}
Run the Webhook
go run main.go
Expose to the Internet
Use ngrok:
ngrok http 3000
Python (Flask)
Setup Environment and Install Dependencies
mkdir python-webhook
cd python-webhook
python3 -m venv venv
source venv/bin/activate
pip install flask
Create app.py
from flask import Flask, request, Response
import json
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
print('Received webhook. Request details:')
print('Headers:', json.dumps(dict(request.headers), indent=2))
data = request.get_data()
try:
json_data = json.loads(data)
print('Parsed JSON data:')
print(json.dumps(json_data, indent=2))
except json.JSONDecodeError as e:
print('Error parsing JSON:', str(e))
print('Raw body:', data.decode())
return Response('Webhook received', status=200)
if __name__ == '__main__':
app.run(port=3000)
Run the webhook
node app.py
Expose to the Internet
Use ngrok:
ngrok http 3000
Ruby (Sinatra)
Setup Environment and Install Dependencies
mkdir ruby-webhook
cd ruby-webhook
echo "source 'https://rubygems.org'" > Gemfile
echo "gem 'sinatra'" >> Gemfile
bundle install
Create app.rb
require 'sinatra'
require 'json'
set :port, 3000
post '/webhook' do
puts 'Received webhook. Request details:'
puts "Headers: #{JSON.pretty_generate(headers)}"
request.body.rewind
payload = request.body.read
begin
json_data = JSON.parse(payload)
puts 'Parsed JSON data:'
puts JSON.pretty_generate(json_data)
rescue JSON::ParserError => e
puts "Error parsing JSON: #{e.message}"
puts "Raw body: #{payload}"
end
status 200
body 'Webhook received'
end
Run the Webhook
ruby app.rb -p 3000
Expose to the Internet
Use ngrok:
ngrok http 3000
PHP
Setup Environment and Run Webhook
mkdir php-webhook
cd php-webhook
echo "<?php
$rawData = file_get_contents('php://input');
echo "Received webhook. Request details:\n";
echo "Headers:\n";
echo json_encode(getallheaders(), JSON_PRETTY_PRINT) . "\n";
$jsonData = json_decode($rawData);
if (json_last_error() === JSON_ERROR_NONE) {
echo "Parsed JSON data:\n";
echo json_encode($jsonData, JSON_PRETTY_PRINT) . "\n";
} else {
echo "Error parsing JSON: " . json_last_error_msg() . "\n";
echo "Raw body: $rawData\n";
}
http_response_code(200);
echo 'Webhook received';
?>" > webhook.php
php -S localhost:3000
Expose to the Internet
Use ngrok:
ngrok http 3000
Java
Setup Environment and Install Dependencies
mkdir java-webhook
cd java-webhook
Create WebhookServer.java
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
public class WebhookServer {
public static void main(String[] args) throws IOException {
int port = 3000;
HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
server.createContext("/webhook", new WebhookHandler());
server.setExecutor(null);
server.start();
System.out.println("Server is running on port " + port);
}
static class WebhookHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
if ("POST".equals(exchange.getRequestMethod())) {
System.out.println("Received webhook. Request details:");
// Log headers
System.out.println("Headers:");
exchange.getRequestHeaders().forEach((key, values) ->
System.out.println(key + ": " + String.join(", ", values)));
// Read and log body
InputStream requestBody = exchange.getRequestBody();
byte[] bodyBytes = requestBody.readAllBytes();
String body = new String(bodyBytes, StandardCharsets.UTF_8);
if (body.isEmpty()) {
System.out.println("Body: Empty request received");
} else {
System.out.println("Body:");
System.out.println(body);
}
// Send response
String response = "Webhook received";
exchange.sendResponseHeaders(200, response.length());
try (OutputStream os = exchange.getResponseBody()) {
os.write(response.getBytes());
}
} else {
// Handle non-POST requests
String response = "Method Not Allowed";
exchange.sendResponseHeaders(405, response.length());
try (OutputStream os = exchange.getResponseBody()) {
os.write(response.getBytes());
}
}
}
}
}
Run the Webhook
javac WebhookServer.java
java WebhookServer
Expose to the Internet
Use ngrok:
ngrok http 3000
Rust (Actix-web)
Setup Environment and Install Dependencies
cargo new rust-webhook
cd rust-webhook
Add dependencies to Cargo.toml
[dependencies]
actix-web = "4.0"
serde_json = "1.0"
Create src/main.rs
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use serde_json::Value;
async fn webhook(body: String) -> impl Responder {
println!("Received webhook. Request details:");
match serde_json::from_str::<Value>(&body) {
Ok(json) => {
println!("Parsed JSON data:");
println!("{}", serde_json::to_string_pretty(&json).unwrap());
},
Err(e) => {
println!("Error parsing JSON: {}", e);
println!("Raw body: {}", body);
}
}
HttpResponse::Ok().body("Webhook received")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().route("/webhook", web::post().to(webhook))
})
.bind("127.0.0.1:3000")?
.run()
.await
}
Run the Webhook
cargo run
Expose to the Internet
Use ngrok:
ngrok http 3000
More resources
We ❤️ Feedback!
If you have any feedback or questions about this documentation, let us know. We'd love to hear from you!
Also, check out the QuickNode Forum for more resources. Stay up to date with the latest by following us on Twitter (@QuickNode) or Discord.