Skip to content

Commit c6e2090

Browse files
committed
Backend Concurrency for Endpoint Details
1 parent 535247c commit c6e2090

2 files changed

Lines changed: 64 additions & 45 deletions

File tree

internal/api/endpoint.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package api
2+
3+
import (
4+
"net/http"
5+
"sync"
6+
7+
"certui/internal/certificate"
8+
"certui/internal/domain"
9+
)
10+
11+
// EndpointDetails contains the certificate, domain, and WHOIS details for an endpoint.
12+
type EndpointDetails struct {
13+
Domain domain.DomainDetails
14+
Whois *domain.WhoisDetails
15+
SSL *certificate.SSLDetails
16+
}
17+
18+
// fetchEndpointDetails fetches certificate, domain, and WHOIS details concurrently for a single endpoint
19+
func fetchEndpointDetails(client *http.Client, endpoint domain.Domain) *EndpointDetails {
20+
var ssl *certificate.SSLDetails
21+
var domainDetails domain.DomainDetails
22+
var whoisDetails *domain.WhoisDetails
23+
var wg sync.WaitGroup
24+
25+
wg.Add(3)
26+
go func() { defer wg.Done(); ssl, _ = certificate.GetCertificateInfo(client, endpoint) }()
27+
go func() { defer wg.Done(); domainDetails = domain.GetDomainDetails(endpoint) }()
28+
go func() { defer wg.Done(); whoisDetails, _ = domain.WhoisForDomain(endpoint) }()
29+
wg.Wait()
30+
31+
return &EndpointDetails{Domain: domainDetails, Whois: whoisDetails, SSL: ssl}
32+
}

internal/api/handlers.go

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,32 @@ import (
44
"encoding/json"
55
"fmt"
66
"net/http"
7+
"sync"
78
"time"
89

9-
"certui/internal/certificate"
1010
"certui/internal/config"
1111
"certui/internal/domain"
1212
)
1313

14-
type EndpointDetails struct {
15-
Domain domain.DomainDetails
16-
Whois *domain.WhoisDetails
17-
SSL *certificate.SSLDetails
18-
}
19-
2014
// AllEndpointsHandler handles requests for all Endpoints Details
2115
func AllEndpointsHandler(cfg *config.Config) http.HandlerFunc {
2216
return func(w http.ResponseWriter, r *http.Request) {
2317
results := make(map[domain.Domain]*EndpointDetails)
18+
var mu sync.Mutex
19+
var wg sync.WaitGroup
20+
2421
client := &http.Client{}
2522
for _, endpoint := range cfg.Endpoints {
26-
endpointDomain := domain.Domain(endpoint)
27-
28-
ssl, err := certificate.GetCertificateInfo(client, endpointDomain)
29-
if err != nil {
30-
ssl = nil
31-
}
32-
33-
domainDetails := domain.GetDomainDetails(endpointDomain)
34-
35-
whoisDetails, err := domain.WhoisForDomain(endpointDomain)
36-
if err != nil {
37-
whoisDetails = nil
38-
}
39-
40-
response := EndpointDetails{
41-
Domain: domainDetails,
42-
Whois: whoisDetails,
43-
SSL: ssl,
44-
}
45-
46-
results[endpoint] = &response
23+
wg.Add(1)
24+
go func(ep domain.Domain) {
25+
defer wg.Done()
26+
details := fetchEndpointDetails(client, ep)
27+
mu.Lock()
28+
results[ep] = details
29+
mu.Unlock()
30+
}(endpoint)
4731
}
32+
wg.Wait()
4833

4934
w.Header().Set("Content-Type", "application/json")
5035
json.NewEncoder(w).Encode(results)
@@ -58,27 +43,29 @@ func EndpointHandlerSSE(cfg *config.Config) http.HandlerFunc {
5843
w.Header().Set("Cache-Control", "no-cache")
5944
w.Header().Set("Connection", "keep-alive")
6045

46+
var mu sync.Mutex
47+
var wg sync.WaitGroup
48+
6149
client := &http.Client{Timeout: 10 * time.Second}
6250
for _, endpoint := range cfg.Endpoints {
63-
endpointDomain := domain.Domain(endpoint)
64-
ssl, _ := certificate.GetCertificateInfo(client, endpointDomain)
65-
domainDetails := domain.GetDomainDetails(endpointDomain)
66-
whoisDetails, _ := domain.WhoisForDomain(endpointDomain)
51+
wg.Add(1)
52+
go func(ep domain.Domain) {
53+
defer wg.Done()
54+
details := fetchEndpointDetails(client, ep)
55+
wrapped := struct {
56+
Endpoint domain.Domain `json:"endpoint"`
57+
Details EndpointDetails `json:"details"`
58+
}{Endpoint: ep, Details: *details}
6759

68-
response := EndpointDetails{
69-
Domain: domainDetails,
70-
Whois: whoisDetails,
71-
SSL: ssl,
72-
}
73-
wrapped := struct {
74-
Endpoint domain.Domain `json:"endpoint"`
75-
Details EndpointDetails `json:"details"`
76-
}{Endpoint: endpoint, Details: response}
77-
78-
b, _ := json.Marshal(wrapped)
79-
fmt.Fprintf(w, "data: %s\n\n", b) // Send Single Endpoint Data
80-
w.(http.Flusher).Flush()
60+
b, _ := json.Marshal(wrapped)
61+
mu.Lock()
62+
fmt.Fprintf(w, "data: %s\n\n", b) // Send Single Endpoint Data
63+
w.(http.Flusher).Flush()
64+
mu.Unlock()
65+
}(endpoint)
8166
}
67+
wg.Wait()
68+
8269
fmt.Fprintf(w, "event: done\ndata: {}\n\n") // Send Done Event
8370
w.(http.Flusher).Flush()
8471
}

0 commit comments

Comments
 (0)