Skip to content

Instantly share code, notes, and snippets.

@axyz
Created September 14, 2023 07:46
Show Gist options
  • Save axyz/78271988f6597ac60fc5a54748ec47d0 to your computer and use it in GitHub Desktop.
Save axyz/78271988f6597ac60fc5a54748ec47d0 to your computer and use it in GitHub Desktop.
Encode code string in a compressed URL string
import { strToU8, strFromU8, compressSync, decompressSync } from "fflate";
const urlEncode = (str: string) =>
btoa(str).replace(
/[/+=]/g,
(a) => ({ "/": "-", "+": "_", "=": "~" }[a] || a)
);
const urlDecode = (str: string) =>
atob(str.replace(/[-_~]/g, (a) => ({ "-": "/", _: "+", "~": "=" }[a] || a)));
const deflate = (str: string) =>
strFromU8(compressSync(strToU8(str), { level: 9 }), true);
const inflate = (str: string) => strFromU8(decompressSync(strToU8(str, true)));
export function encode(string: string) {
return urlEncode(deflate(string));
}
export function decode(string: string) {
return inflate(urlDecode(string));
}
@sylvesteraswin
Copy link

Go implementation

package main

import (
	"bytes"
	"compress/flate"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"

	"github.com/gorilla/mux"
)

type HashResults struct {
	HashData string `json:"hash"`
}

type RequestBody struct {
	ChartProps string `json:"chartProps"`
}

func hash(input string) (string, error) {
	// Create a buffer to hold the compressed data
	var compressedBuffer bytes.Buffer

	// Create a flate.Writer with the default compression level
	writer, err := flate.NewWriter(&compressedBuffer, flate.DefaultCompression)
	if err != nil {
		return "", err
	}

	// Write the input string to the flate.Writer, which compresses it
	_, err = writer.Write([]byte(input))
	if err != nil {
		return "", err
	}

	// Close the flate.Writer to flush any remaining data
	writer.Close()

	// Get the compressed data as a byte slice
	compressedData := compressedBuffer.Bytes()

	// Convert the compressed data to base64
	compressedBase64 := base64.StdEncoding.EncodeToString(compressedData)

	encodedString := url.QueryEscape(compressedBase64)

	// Create a HashResults struct to hold the base64 encoded data
	result := HashResults{
		HashData: encodedString,
	}

	// Marshal the result struct into JSON
	jsonResult, err := json.Marshal(result)
	if err != nil {
		return "", err
	}

	return string(jsonResult), nil
}

func imageHandler(w http.ResponseWriter, r *http.Request) {

	// Declare a new RequestBody struct.
	var rb RequestBody

	// Try to decode the request body into the struct. If there is an error,
	// respond to the client with the error message and a 400 status code.
	err := json.NewDecoder(r.Body).Decode(&rb)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	// // Input string to be compressed
	input := rb.ChartProps

	fmt.Println("rb is:", rb)
	fmt.Println("input is:", input)

	// Call the hash function with the input string
	jsonResult, err := hash(input)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, string(err.Error()))
		return
	}

	// fmt.Fprintf(w, string(compressedData))
	w.WriteHeader(http.StatusOK)
	// w.Header().Set("Content-Type", "application/json")
	// fmt.Fprintf(w, string(jsonResult))
	w.Write([]byte(jsonResult))
}

func commonMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Do stuff here
		w.Header().Add("Content-Type", "application/json")
		// Call the next handler, which can be another middleware in the chain, or the final handler.
		next.ServeHTTP(w, r)
	})
}

func main() {
	router := mux.NewRouter()
	router.Use(commonMiddleware)
	router.HandleFunc("/image", imageHandler).Methods("POST")

	server := &http.Server{
		Addr:    ":8080",
		Handler: router,
	}

	fmt.Println("Server started")
	server.ListenAndServe()
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment