mirror of https://github.com/mpolden/echoip
Implemented feedback and fixes
This commit is contained in:
parent
313481d2a5
commit
5a32d37286
2
Makefile
2
Makefile
|
@ -71,4 +71,4 @@ endif
|
|||
@sha256sum $(GOPATH)/bin/$(XBIN)
|
||||
|
||||
run:
|
||||
go run cmd/echoip/main.go -a data/asn.mmdb -c data/city.mmdb -f data/country.mmdb -H x-forwarded-for -r
|
||||
go run cmd/echoip/main.go -a data/asn.mmdb -c data/city.mmdb -f data/country.mmdb -H x-forwarded-for -r -s
|
||||
|
|
|
@ -39,6 +39,7 @@ func main() {
|
|||
template := flag.String("t", "html", "Path to template dir")
|
||||
cacheSize := flag.Int("C", 0, "Size of response cache. Set to 0 to disable")
|
||||
profile := flag.Bool("P", false, "Enables profiling handlers")
|
||||
sponsor := flag.Bool("s", false, "Show sponsor logo")
|
||||
var headers multiValueFlag
|
||||
flag.Var(&headers, "H", "Header to trust for remote IP, if present (e.g. X-Real-IP)")
|
||||
flag.Parse()
|
||||
|
@ -64,6 +65,10 @@ func main() {
|
|||
log.Println("Enabling port lookup")
|
||||
server.LookupPort = iputil.LookupPort
|
||||
}
|
||||
if *sponsor {
|
||||
log.Println("Enabling sponsor logo")
|
||||
server.Sponsor = *sponsor
|
||||
}
|
||||
if len(headers) > 0 {
|
||||
log.Printf("Trusting remote IP from header(s): %s", headers.String())
|
||||
}
|
||||
|
|
134
html/index.html
134
html/index.html
|
@ -8,9 +8,10 @@
|
|||
name="description"
|
||||
content="ifconfig. What is my IP address? — The best tool to find your own IP address, and information about it."
|
||||
/>
|
||||
<link rel="canonical" href="https://ifconfig.co/" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300,500;1,300,500&display=swap"
|
||||
href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,400;0,700;1,400&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
|
@ -41,20 +42,28 @@
|
|||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-1-3 align-right">
|
||||
<div class="l-box">
|
||||
<div class="leafcloud-logo">
|
||||
<a href="https://www.leaf.cloud?utm_source=ifconfig">
|
||||
{{ template "leafcloud-logo.svg" "." }}
|
||||
</a>
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
{{ if .Sponsor }}
|
||||
<div class="l-box leafcloud-placement">
|
||||
<div class="pure-g">
|
||||
<div class="pure-u pure-u-md-1">
|
||||
<div class="leafcloud-logo">
|
||||
<a href="https://www.leaf.cloud?utm_source=ifconfig">
|
||||
{{ template "leafcloud-logo.svg" "." }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u pure-u-md-1">
|
||||
<p>
|
||||
This site is graciously hosted by<br />
|
||||
<a href="https://www.leaf.cloud?utm_source=ifconfig"
|
||||
>Leafcloud – The Truly Sustainable Cloud</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
This site is graciously hosted by<br />
|
||||
<a href="https://www.leaf.cloud?utm_source=ifconfig"
|
||||
>Leafcloud – The Truly Sustainable Cloud</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -62,7 +71,7 @@
|
|||
<!-- COLUMN 1 -->
|
||||
<div class="pure-u-1 pure-u-md-1-2 col">
|
||||
<div class="l-box">
|
||||
<h2>What do we know about this IP Adress?</h2>
|
||||
<h2>What do we know about this IP Address?</h2>
|
||||
<table class="info-table">
|
||||
<tr>
|
||||
<th scope="row">IP Address</th>
|
||||
|
@ -159,13 +168,13 @@
|
|||
</tr>
|
||||
{{ end }} {{ end }}
|
||||
</table>
|
||||
{{ if .Country }}
|
||||
<p>
|
||||
This information is provided from the GeoLite2 database created by
|
||||
MaxMind, available from
|
||||
<a href="https://www.maxmind.com">www.maxmind.com</a>
|
||||
</p>
|
||||
|
||||
{{ if .City }}
|
||||
{{ end }} {{ if .City }}
|
||||
<div class="pure-u-1 pure-u-md-1-1">
|
||||
<h2>Map</h2>
|
||||
<iframe
|
||||
|
@ -195,104 +204,89 @@
|
|||
<button
|
||||
name="ip"
|
||||
class="button widget-select"
|
||||
onclick="changeInput(this.name)"
|
||||
onclick="changeInput(this.name, this)"
|
||||
>
|
||||
ip
|
||||
</button>
|
||||
<button
|
||||
name="country"
|
||||
class="button widget-select"
|
||||
onclick="changeInput(this.name)"
|
||||
onclick="changeInput(this.name, this)"
|
||||
>
|
||||
country
|
||||
</button>
|
||||
<button
|
||||
name="country-iso"
|
||||
class="button widget-select"
|
||||
onclick="changeInput(this.name)"
|
||||
onclick="changeInput(this.name, this)"
|
||||
>
|
||||
country-iso
|
||||
</button>
|
||||
<button
|
||||
name="city"
|
||||
class="button widget-select"
|
||||
onclick="changeInput(this.name)"
|
||||
onclick="changeInput(this.name, this)"
|
||||
>
|
||||
city
|
||||
</button>
|
||||
<button
|
||||
name="asn"
|
||||
class="button widget-select"
|
||||
onclick="changeInput(this.name)"
|
||||
onclick="changeInput(this.name, this)"
|
||||
>
|
||||
ASN
|
||||
</button>
|
||||
<button
|
||||
name="json"
|
||||
class="button widget-select"
|
||||
onclick="changeInput(this.name)"
|
||||
onclick="changeInput(this.name, this)"
|
||||
>
|
||||
JSON
|
||||
</button>
|
||||
<button
|
||||
name="port"
|
||||
class="button widget-select"
|
||||
onclick="changeInput(this.name, this)"
|
||||
>
|
||||
port
|
||||
</button>
|
||||
<input
|
||||
id="portInput"
|
||||
type="number"
|
||||
min="1"
|
||||
max="40000"
|
||||
value="8080"
|
||||
class="narrow-input pure-input"
|
||||
placeholder="8080"
|
||||
onchange="updatePort(this.value)"
|
||||
/>
|
||||
</div>
|
||||
<div class="widgetbox input">
|
||||
<code id="command"></code>
|
||||
</div>
|
||||
<div id="output" class="widgetbox output"></div>
|
||||
|
||||
<table class="input-table">
|
||||
<tr>
|
||||
<td colspan="3">You can open this page for another IP</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input
|
||||
id="ipCheckBox"
|
||||
type="checkbox"
|
||||
class="toggle"
|
||||
onchange="enableIP(this)"
|
||||
/>
|
||||
</td>
|
||||
<td>Check Another IP</td>
|
||||
<td>
|
||||
<form class="pure-form">
|
||||
<fieldset>
|
||||
<label for="ipCheckBox">
|
||||
Check another IP
|
||||
<input
|
||||
id="ipInput"
|
||||
class="narrow-input"
|
||||
class="medium-input pure-input"
|
||||
type="text"
|
||||
placeholder="1.1.1.1"
|
||||
onkeyup="updateIP(this)"
|
||||
onkeyup="updateIP(this.value)"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<button onclick="navigate()">open</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
And you can check if a port on your IP is open
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input
|
||||
id="portCheckBox"
|
||||
type="checkbox"
|
||||
class="toggle"
|
||||
onchange="enablePort(this)"
|
||||
/>
|
||||
</td>
|
||||
<td>Check For Port</td>
|
||||
<td>
|
||||
<input
|
||||
id="portInput"
|
||||
type="text"
|
||||
class="narrow-input"
|
||||
placeholder="8080"
|
||||
/>
|
||||
</td>
|
||||
<td><button onclick="getQuery()">go</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</label>
|
||||
<button
|
||||
type="button"
|
||||
class="pure-button"
|
||||
onclick="navigate()"
|
||||
>
|
||||
Open
|
||||
</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- FAQ -->
|
||||
|
|
106
html/script.html
106
html/script.html
|
@ -6,7 +6,7 @@
|
|||
let commandBox, widgetBox, compositePath, commandStr;
|
||||
let path
|
||||
let ipQuery, portQuery
|
||||
let ipCheckBox, portCheckBox
|
||||
let ipCheckBox, portCheckBox, portInput
|
||||
let ip = ''
|
||||
|
||||
window.onload = (event) => {
|
||||
|
@ -14,6 +14,7 @@
|
|||
widgetBox = document.getElementById('output');
|
||||
ipCheckBox = document.getElementById('ipCheckBox')
|
||||
portCheckBox = document.getElementById('portCheckBox')
|
||||
portInput = document.getElementById('portInput')
|
||||
reset()
|
||||
setcommdStr()
|
||||
changeInput("ip")
|
||||
|
@ -26,80 +27,63 @@
|
|||
}
|
||||
|
||||
function setcommdStr() {
|
||||
compositePath = `${path}${ipQuery}${portQuery}`;
|
||||
compositePath = `${path}${portQuery}${ipQuery}`;
|
||||
commandStr = `${tool} ${host}/${compositePath}`;
|
||||
commandBox.innerText = commandStr;
|
||||
}
|
||||
|
||||
function changeInput(input) {
|
||||
function changeInput(input, button) {
|
||||
path = input
|
||||
portCheckBox.checked = false;
|
||||
portQuery = ""
|
||||
if (path === "json") {
|
||||
output.innerText = jsonObj
|
||||
} else if (path === "country-iso") {
|
||||
output.innerText = data["country_iso"]
|
||||
portInput.classList.add("hidden");
|
||||
switch(path) {
|
||||
case "json":
|
||||
output.innerText = jsonObj
|
||||
break
|
||||
case "country-iso":
|
||||
output.innerText = data["country_iso"]
|
||||
break
|
||||
case "port":
|
||||
portInput.classList.remove("hidden");
|
||||
path = "port";
|
||||
output.innerText = "{}";
|
||||
let currentPort = document.querySelector("#portInput").value;
|
||||
updatePort(currentPort);
|
||||
break
|
||||
case "ip":
|
||||
output.innerText = data["ip"]
|
||||
path = ""
|
||||
break
|
||||
default:
|
||||
output.innerText = data[path]
|
||||
}
|
||||
else {
|
||||
output.innerText = data[path]
|
||||
if (path === "ip") { path = "" }
|
||||
setcommdStr();
|
||||
|
||||
// set button selected
|
||||
if (button) {
|
||||
allButtons = document.querySelectorAll(('button.selected'));
|
||||
allButtons.forEach((btn) => {btn.classList.remove("selected")})
|
||||
|
||||
button.classList.add("selected");
|
||||
}
|
||||
setcommdStr()
|
||||
}
|
||||
|
||||
function enableIP(cb) {
|
||||
portCheckBox.checked = false;
|
||||
// reset();
|
||||
if (cb.checked) {
|
||||
ipQuery = `?ip=${ip}`;
|
||||
portQuery = ""
|
||||
} else {
|
||||
ipQuery = '';
|
||||
}
|
||||
setcommdStr()
|
||||
}
|
||||
|
||||
function enablePort(cb) {
|
||||
ipCheckBox.checked = false;
|
||||
reset();
|
||||
if (cb.checked) {
|
||||
portQuery = "port/8080";
|
||||
ipQuery = "";
|
||||
} else {
|
||||
portQuery = '';
|
||||
}
|
||||
setcommdStr()
|
||||
}
|
||||
|
||||
function getQuery() {
|
||||
fetch(compositePath, {
|
||||
headers: {
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
console.log(response.headers)
|
||||
if (response.headers.get('Content-Type') === "application/json") {
|
||||
console.log("its json")
|
||||
return response.json()
|
||||
} else {
|
||||
return response.text()
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
// console.log(data)
|
||||
output.innerText = JSON.stringify(data);
|
||||
})
|
||||
}
|
||||
|
||||
function navigate() {
|
||||
function navigate(event) {
|
||||
console.log("navigate", compositePath)
|
||||
window.location = compositePath
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
function updateIP(input) {
|
||||
ip = input.value
|
||||
function updatePort(value) {
|
||||
port = value
|
||||
portQuery = `/${port}`
|
||||
setcommdStr()
|
||||
}
|
||||
|
||||
function updateIP(value) {
|
||||
ip = value
|
||||
ipQuery = `?ip=${ip}`;
|
||||
setcommdStr()
|
||||
console.log(ip)
|
||||
changeInput("ip", null)
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -89,67 +89,18 @@
|
|||
}
|
||||
|
||||
.narrow-input {
|
||||
width: 5.5em;
|
||||
}
|
||||
|
||||
.medium-input {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
/* TOGGLE */ /* https://codepen.io/avstorm/pen/jOEpBLW */
|
||||
input[type="checkbox"] {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type="checkbox"]:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
height: 26px;
|
||||
width: 41px;
|
||||
border-radius: 12px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
border: 2px solid #474755;
|
||||
background: rgb(249, 249, 249);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.toggle:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(180deg, #a5a8b8 0%, #1f2027 100%);
|
||||
box-shadow: 0 1px 2px rgba(44, 44, 44, 0.2);
|
||||
transition: all 0.2s cubic-bezier(0.5, 0.1, 0.75, 1.35);
|
||||
}
|
||||
.toggle:checked {
|
||||
/* border-color: #654fec; */
|
||||
background: rgb(45, 45, 45);
|
||||
transition: all 0.2s cubic-bezier(0.5, 0.1, 0.75, 1.35);
|
||||
}
|
||||
.toggle:checked:after {
|
||||
transform: translatex(15px);
|
||||
transition: all 0.2s ease;
|
||||
background: rgb(220, 220, 220);
|
||||
/* background: linear-gradient(180deg, #a5a8b8 0%, #1f2027 100%); */
|
||||
button.selected {
|
||||
background-color: rgb(208 208 208);
|
||||
}
|
||||
|
||||
/* POST CORRECTION */
|
||||
.input-table td {
|
||||
padding: 0rem 0.3rem;
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
.leafcloud-logo {
|
||||
height: 80px;
|
||||
margin: 2em 0 -0.5em 0;
|
||||
}
|
||||
|
||||
.leafcloud-logo .letters {
|
||||
fill: black;
|
||||
}
|
||||
|
@ -191,9 +142,42 @@
|
|||
button {
|
||||
background-color: #2e2e2e;
|
||||
}
|
||||
button.selected {
|
||||
background-color: rgb(125 125 125);
|
||||
}
|
||||
|
||||
.pure-input {
|
||||
background-color: #e6e6e6;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.pure-input::placeholder {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.leafcloud-logo .letters {
|
||||
fill: white;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.leafcloud-placement {
|
||||
text-align: right;
|
||||
}
|
||||
.leafcloud-logo {
|
||||
height: 80px;
|
||||
margin: 2em 0 -0.5em 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.leafcloud-logo {
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.debug {
|
||||
outline: 1px dotted pink;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -33,6 +33,7 @@ type Server struct {
|
|||
cache *Cache
|
||||
gr geo.Reader
|
||||
profile bool
|
||||
Sponsor bool
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
|
@ -53,6 +54,7 @@ type Response struct {
|
|||
ASNOrg string `json:"asn_org,omitempty"`
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
UserAgent *useragent.UserAgent `json:"user_agent,omitempty"`
|
||||
Sponsor bool `json:"sponsor"`
|
||||
}
|
||||
|
||||
type PortResponse struct {
|
||||
|
@ -160,6 +162,7 @@ func (s *Server) newResponse(r *http.Request) (Response, error) {
|
|||
ASN: autonomousSystemNumber,
|
||||
ASNOrg: asn.AutonomousSystemOrganization,
|
||||
Hostname: hostname,
|
||||
Sponsor: s.Sponsor,
|
||||
}
|
||||
s.cache.Set(ip, response)
|
||||
response.UserAgent = userAgentFromRequest(r)
|
||||
|
|
Loading…
Reference in New Issue