Full Blog TOC

Full Blog Table Of Content with Keywords Available HERE

Thursday, July 24, 2025

React Application Using Vite

 




In recent years it seems that Vite is replacing the old known create-react-app. I've gave it a try, and it is working great. By comparison to create-react-app, it is faster and has a better flexible configuration preventing the need the eject. Listed below are the basic steps to create a react-redux application including CSS modules and async thunk requests.


Installation


To start we need to have a recent NPM & Node installed, so we better update it using NVM:


nvm install --lts


Next we run the command to create our new project:


npm create vite@latest


And we follow the instructions until the project is created, and we can run it:

cd my-vite
npm install
npm run dev


We add the redux support:

npm install -S @reduxjs/toolkit react-redux


And we can start the development.


Framework Code


We create the redux main store (it includes import to the component that we will add later).


store.jsx

import {configureStore} from '@reduxjs/toolkit'

import box from "./component/box/slice.jsx"

export const store = configureStore({
middleware: (getDefaultMiddleware) => getDefaultMiddleware({
immutableCheck: {ignoredPaths: ['graph']},
serializableCheck: {ignoredPaths: ['graph']},
}),
reducer: {
box,
},
})

export default store


We import this store in our main code.


main.jsx

import {StrictMode} from 'react'
import {createRoot} from 'react-dom/client'
import './index.css'
import App from './App.jsx'
import {Provider} from 'react-redux'
import store from './store'

createRoot(document.getElementById('root')).render(
<StrictMode>
<Provider store={store}>
<App/>
</Provider>
</StrictMode>,
)


We update the application to include our new component (again we will descibe it later).


App.jsx

import {useState} from 'react'
import './App.css'
import Box from "./component/box/component.jsx";

function App() {
const [count, setCount] = useState(0)

return (
<>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
</div>
<Box
name="my-box"
/>
</>
)
}

export default App


The last thing to do it to add wrapper for calling to APIs.


request.jsx


export async function sendRequest(url, body) {
let fetchOptions = {
method: 'post',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify(body),
}

const response = await fetch(url, fetchOptions)

if (response.status === 200) {
const json = await response.json()
return {
ok: true,
response: json,
}
}

let error = await response.text()
try {
const parsed = JSON.parse(error)
if (parsed.message) {
error = parsed.message
}
} catch (e) {
// ignore - send the actual error text
}

return {
ok: false,
response: error,
}
}


Application Code


The last thing to do it to add our box component which like most components includes 3 files: the component GUI, the redux slice, and the CSS module.


component.jsx

import React from 'react'
import {useDispatch, useSelector} from 'react-redux'
import {selectState, updateBox, updateMyData} from './slice'
import styles from './component.module.css'


function Box(props) {
const {name} = props
const dispatch = useDispatch()
const state = useSelector(selectState)
const {boxWidth} = state

function clickHandler() {
dispatch(updateBox({doubleClick: false}))
}

function doubleClickHandler() {
dispatch(updateMyData())
dispatch(updateBox({doubleClick: true}))
}

const dynamicStyle = {
width: `${boxWidth}px`,
}

return (
<div
className={styles.boxStyle}
onClick={clickHandler}
onDoubleClick={doubleClickHandler}
style={dynamicStyle}
>
{name}
</div>
)
}

export default Box


component.module.css


.boxStyle{
background: blue;
color: yellow;
font-size: large;
font-weight: bold;
}


slice.jsx

import {createAsyncThunk, createSlice} from '@reduxjs/toolkit'
import {sendRequest} from "../request/request.jsx";


const initialState = {
boxWidth: 100,
}


export const updateMyData = createAsyncThunk(
'box/updateMyData',
async (input, thunkApi) => {
const state = thunkApi.getState()
const {box} = state
const {boxWidth} = box
const body = {
WIDTH: boxWidth,
}
const {response, ok} = await sendRequest('http://localhost:3000/my-api', body)

if (!ok) {
console.error(response)
return
}

console.log(response)
},
)

export const slice = createSlice({
name: 'box',
initialState,
reducers: {
updateBox: (state, action) => {
const {doubleClick} = action.payload
if (doubleClick) {
state.boxWidth = 100
} else {
state.boxWidth += 100
}
},
},
})

export const {updateBox} = slice.actions

export const selectState = (state) => state.box


export default slice.reducer


Final Note


I recommend using Vite since it is much faster and the result transpiled code works faster. It is alos a living project unlike the create-react-app which seems near death.


Sunday, July 20, 2025

Create a Valid SSL Certificate for AWS EKS Ingress

 



Creating a valid SSL certificate for AWS EKS Ingress is pretty simple if you know what do to.

Notice that you can also check the post Setting Up a Publicly Accessible VM with Docker, Nginx, and SSL on GCP.


Before starting, make sure you own a DNS zone that you can update. Let assume this DNS zone is for my-demo.com, and now we want the have my-site.my-demo.com as a valid SSL certificate that would direct into an EKS ingress that would direct it to a specific service.


We start by a certificate request from ACM:


aws acm request-certificate \
--domain-name "my-site.my-demo.com" \
--validation-method DNS \
--idempotency-token myappcert \
--region us-east-1 \
--subject-alternative-names "*.my-demo.com"


The output would specify the certificate ARN, for example:


"CertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-4f3e-a5d6-d067a159d981"


We need to add this as annotation to our ingress:


alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-4f3e-a5d6-d067a159d981
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'


Make sure the ingress also includes the following under the "spec".


ingressClassName: alb
tls:
- hosts:
- my-site.my-demo.com

We follow by describing the certificate use the ARN we just got in the output.


aws acm describe-certificate \
--certificate-arn arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-4f3e-a5d6-d067a159d981


In the description output we would find the DNS challenge:


"ResourceRecord": {
"Name": "_6a234567890345678934567e76822dee.my-site.my-demo.com.",
"Type": "CNAME",
"Value": "_9ce23456789345678934567894567657.xlfgrmvvlj.acm-validations.aws."
},


Now we need to fulfill this challenge by adding a CNAME in our DNS zone from the "Name" to the "Value". Once we add this we need to wait ~15 minutes and then we we access the valid SSL connection https://my-site.my-demo.com 







Sunday, July 13, 2025

HTTP Requests General Anonymizer



In this post we will review the steps required to create an HTTP requests anonymizer. 


Anonymizing an HTTP request is required in case we want to store the HTTP requests sent to a site or a web service. We can then use this stored data internally to perform research without exposing the customer Personally Identifiable Information aka PII.

Anonymization of an HTTP request should handle the following items:

  • The request path
  • The user agent header
  • The cookies
  • The source IP
  • General headers treatment

Lets review how to handle the request path as an example that can be later applies to most of the HTTP request items. The request path is compound of multiple sections, for example the path:

/api/v3/store/2345678/item/86767/update-credit/1111-1111-1111-1111

contains multiple sections separated by a slash character. To address anonymization of the path we should treat each section on it own, trying to identify known PII items.

The first PII type to search for is a country ID, for example Brazil ID, US SSN, France ID, etc.
Notice that each country ID has its own structure, its own ignored separator characters, and its own parity number to check. You can easily us pre-made libraries to identify these IDs such as python-stdnum. Alternatively use AI engine such as ChatGPT to create a short code to identify a specific country ID.

Other PII types to search for are:
  • Gender
  • Address
  • Person name
  • Email
  • Credit card
  • Passport number
  • Zip code
  • Phone number
Any of these type has its own method for searching, for example a person name can be identified by holding a list known 100K names. An alternative is using a LLM engine to find PII, but this has much higher costs.

Once we detect a PII we need to replace the PII value with the anonymized value. We can keep some information about the PII value, for example its type and it length. The request path above could be anonymized to:

/api/v3/store/$$$GENERAL_ID$LEN7$$$/item//$$$GENERAL_ID$LEN5$$$/update-credit//$$$CREDIT_CARD$LEN19$$$

Notice that an anonymizer might have both:
  1. False Positive - when a non PII field is anonymized
  2. False Negative - when a PII field is not anonymized

Like in many fields, there a balance between the False Positives and the False Negative. We would generally prefer more False Positives and less False Negatives since the risk in keeping a non anonymized PII value is high.