added image proxy

This commit is contained in:
admin 2024-04-05 14:15:43 +02:00
parent e382c58434
commit f91830e92e
6 changed files with 104 additions and 18 deletions

View file

@ -23,14 +23,15 @@ This project is a versatile search engine built with Go that leverages external
```bash
git clone https://weforgecode.xyz/Spitfire/Search.git
cd search
go run main.go text.go images.go
go run main.go text.go images.go imageproxy.go
```
## Project Structure
- `main.go`: The entry point of the application, setting up the web server and routing.
- `images.go`: Contains logic for handling image search requests, including fetching data from the Qwant API and preparing it for the template.
- `text.go`: Handles text search requests, fetching results from Google and processing them for display.
- `images.go`: Contains logic for handling image search requests, including fetching data from the Qwant API and preparing it for the template.
- `imageproxy.go`: Part of images.go srach logic, handles image reuslts and displays them using proxy.
- `/templates`: Directory containing HTML templates for rendering the search interface and results.
- `search.html`: The main search page template.
- `images.html`: Template for displaying image search results.

46
imageproxy.go Normal file
View file

@ -0,0 +1,46 @@
package main
import (
"io"
"log"
"net/http"
)
func handleImageProxy(w http.ResponseWriter, r *http.Request) {
// Get the URL of the image from the query string
imageURL := r.URL.Query().Get("url")
if imageURL == "" {
http.Error(w, "URL parameter is required", http.StatusBadRequest)
return
}
// Fetch the image from the external URL
resp, err := http.Get(imageURL)
if err != nil {
log.Printf("Error fetching image: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
defer resp.Body.Close()
// Check if the request was successful
if resp.StatusCode != http.StatusOK {
http.Error(w, "Failed to fetch image", http.StatusBadGateway)
return
}
// Set the Content-Type header to the type of the fetched image
contentType := resp.Header.Get("Content-Type")
if contentType != "" {
w.Header().Set("Content-Type", contentType)
} else {
// Default to octet-stream if Content-Type is not available
w.Header().Set("Content-Type", "application/octet-stream")
}
// Write the image content to the response
if _, err := io.Copy(w, resp.Body); err != nil {
log.Printf("Error writing image to response: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}

View file

@ -69,11 +69,11 @@ func fetchImageResults(query string) ([]ImageSearchResult, error) {
var results []ImageSearchResult
for _, item := range apiResp.Data.Result.Items {
results = append(results, ImageSearchResult{
Thumbnail: item.Thumbnail, // Thumbnail URL
Title: item.Title, // Image title
Media: item.Media, // Direct link to the image - Ensure this field is used appropriately in your template
Source: item.Media, // Using item.Media here ensures the direct image link is used
ThumbProxy: "/img_proxy?url=" + url.QueryEscape(item.Thumbnail), // Proxy URL for the thumbnail, if needed
Thumbnail: item.Thumbnail, // Thumbnail URL
Title: item.Title, // Image title
Media: item.Media, // Direct link to the image - Ensure this field is used appropriately in your template
Source: item.Media, // Using item.Media here ensures the direct image link is used
ThumbProxy: "/img_proxy?url=" + url.QueryEscape(item.Media), // Proxy URL for the thumbnail, if needed
Width: item.Width,
Height: item.Height,
})

View file

@ -73,6 +73,7 @@ func main() {
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
http.HandleFunc("/", handleSearch)
http.HandleFunc("/search", handleSearch)
http.HandleFunc("/img_proxy", handleImageProxy)
fmt.Println("Server is listening on http://localhost:5000")
log.Fatal(http.ListenAndServe(":5000", nil))
}

View file

@ -3,26 +3,64 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image Search Results</title>
<title>{{.Query}} - Spitfire Search</title>
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<div class="header">
<h1>TailsGo</h1>
<form action="/search" method="post" class="search-form" autocomplete="off">
<div class="search-bar">
<input type="text" name="q" value="{{ .Query }}" autofocus id="search-input" placeholder="Type to search..." />
<button type="submit" id="search-btn">Search</button>
</div>
</form>
</div>
<div class="search-results">
<h1>Image Search Results</h1>
{{ if .Results }}
<div class="images-grid">
{{ range .Results }}
<div class="image-item">
<a href="{{ .Source }}" target="_blank">
<img src="{{ .ThumbProxy }}" alt="{{ .Title }}" title="{{ .Title }}">
</a>
<div class="image-info">
<div class="image-title">{{ .Title }}</div>
<div class="image-source">Source: <a href="{{ .Source }}" target="_blank">Visit</a></div>
<div class="images images_viewer_hidden">
<!-- Image Viewer Placeholder - Adapt as necessary -->
<div class="image_view image_hide">
<!-- Navigation and Close for the Image Viewer -->
<!-- Placeholder for dynamic interaction, adapt the onclick functionality as needed -->
<div class="image-view-close">
<button class="btn-nostyle"><div class="material-icons-round icon_visibility clickable">navigate_before</div></button>
<button class="btn-nostyle"><div class="material-icons-round icon_visibility clickable">navigate_next</div></button>
<button class="btn-nostyle"><div class="material-icons-round icon_visibility clickable">close</div></button>
</div>
<!-- Placeholder for selected image -->
<a class="image-viewer-link clickable" href="#">
<div class="view-image">
<img class="view-image-img" src="" alt="Selected Image"/>
</div>
</a>
<!-- Additional image details here -->
</div>
<!-- Images Grid -->
{{ range .Results }}
<div class="image">
<a class="clickable" href="{{ .Source }}" target="_blank">
<img src="{{ .ThumbProxy }}" alt="{{ .Title }}" data-media="{{ .Media }}">
<div class="resolution">{{ .Width }} × {{ .Height }}</div>
<div class="details">
<div class="img_title">{{ .Title }}</div>
<div class="img_source"><a href="{{ .Source }}" target="_blank">Source</a></div>
</div>
</a>
</div>
{{ end }}
</div>
<!-- Pagination -->
<div class="prev-next prev-img">
<!-- Update form action and method according to your app's routing and logic -->
<form action="/search" method="get">
<input type="hidden" name="q" value="{{ .Query }}">
<!-- Pagination buttons, implement pagination logic in your Go handler -->
<button type="submit" name="p" value="previous">Previous</button>
<button type="submit" name="p" value="next">Next</button>
</form>
</div>
{{ else }}
<div class="no-results">No results found for '{{ .Query }}'. Try different keywords.</div>
{{ end }}

View file

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{.Query}} - Search Results</title>
<title>{{.Query}} - Spitfire Search</title>
<link rel="stylesheet" type="text/css" href="/static/css/style.css">
</head>
<body>