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.