added image proxy
This commit is contained in:
parent
33dbefcf6e
commit
8da8999802
5 changed files with 101 additions and 16 deletions
46
imageproxy.go
Normal file
46
imageproxy.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -73,7 +73,7 @@ func fetchImageResults(query string) ([]ImageSearchResult, error) {
|
||||||
Title: item.Title, // Image title
|
Title: item.Title, // Image title
|
||||||
Media: item.Media, // Direct link to the image - Ensure this field is used appropriately in your template
|
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
|
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
|
ThumbProxy: "/img_proxy?url=" + url.QueryEscape(item.Media), // Proxy URL for the thumbnail, if needed
|
||||||
Width: item.Width,
|
Width: item.Width,
|
||||||
Height: item.Height,
|
Height: item.Height,
|
||||||
})
|
})
|
||||||
|
|
1
main.go
1
main.go
|
@ -73,6 +73,7 @@ func main() {
|
||||||
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
||||||
http.HandleFunc("/", handleSearch)
|
http.HandleFunc("/", handleSearch)
|
||||||
http.HandleFunc("/search", handleSearch)
|
http.HandleFunc("/search", handleSearch)
|
||||||
|
http.HandleFunc("/img_proxy", handleImageProxy)
|
||||||
fmt.Println("Server is listening on http://localhost:5000")
|
fmt.Println("Server is listening on http://localhost:5000")
|
||||||
log.Fatal(http.ListenAndServe(":5000", nil))
|
log.Fatal(http.ListenAndServe(":5000", nil))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,26 +3,64 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<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">
|
<link rel="stylesheet" href="/static/css/style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<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">
|
<div class="search-results">
|
||||||
<h1>Image Search Results</h1>
|
<h1>Image Search Results</h1>
|
||||||
{{ if .Results }}
|
{{ if .Results }}
|
||||||
<div class="images-grid">
|
<div class="images images_viewer_hidden">
|
||||||
{{ range .Results }}
|
<!-- Image Viewer Placeholder - Adapt as necessary -->
|
||||||
<div class="image-item">
|
<div class="image_view image_hide">
|
||||||
<a href="{{ .Source }}" target="_blank">
|
<!-- Navigation and Close for the Image Viewer -->
|
||||||
<img src="{{ .ThumbProxy }}" alt="{{ .Title }}" title="{{ .Title }}">
|
<!-- Placeholder for dynamic interaction, adapt the onclick functionality as needed -->
|
||||||
</a>
|
<div class="image-view-close">
|
||||||
<div class="image-info">
|
<button class="btn-nostyle"><div class="material-icons-round icon_visibility clickable">navigate_before</div></button>
|
||||||
<div class="image-title">{{ .Title }}</div>
|
<button class="btn-nostyle"><div class="material-icons-round icon_visibility clickable">navigate_next</div></button>
|
||||||
<div class="image-source">Source: <a href="{{ .Source }}" target="_blank">Visit</a></div>
|
<button class="btn-nostyle"><div class="material-icons-round icon_visibility clickable">close</div></button>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</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 }}
|
{{ else }}
|
||||||
<div class="no-results">No results found for '{{ .Query }}'. Try different keywords.</div>
|
<div class="no-results">No results found for '{{ .Query }}'. Try different keywords.</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<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">
|
<link rel="stylesheet" type="text/css" href="/static/css/style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
Loading…
Add table
Reference in a new issue