mirror of
https://gitlab.com/mangadex-pub/mangadex_at_home.git
synced 2024-01-19 02:48:37 +00:00
Fix downloading of GeoIp2 database
This commit is contained in:
parent
e8f17578de
commit
d2949c6be2
|
@ -27,6 +27,7 @@ dependencies {
|
|||
compileOnly group: "dev.afanasev", name: "sekret-annotation", version: "0.0.7"
|
||||
|
||||
implementation group: "commons-io", name: "commons-io", version: "2.7"
|
||||
implementation group: "org.apache.commons", name: "commons-compress", version: "1.20"
|
||||
implementation group: "ch.qos.logback", name: "logback-classic", version: "1.3.0-alpha4"
|
||||
|
||||
compile 'io.micrometer:micrometer-registry-prometheus:1.6.2'
|
||||
|
|
|
@ -5,15 +5,13 @@ import com.maxmind.geoip2.DatabaseReader
|
|||
import io.micrometer.prometheus.PrometheusMeterRegistry
|
||||
import mdnet.logging.info
|
||||
import mdnet.logging.trace
|
||||
import org.http4k.core.Filter
|
||||
import org.http4k.core.HttpHandler
|
||||
import org.http4k.core.Method
|
||||
import org.http4k.core.Request
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream
|
||||
import org.http4k.core.*
|
||||
import org.http4k.filter.gunzippedStream
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.net.InetAddress
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
||||
class GeoIpMetricsFilter(
|
||||
private val enableGeoIp: Boolean,
|
||||
|
@ -22,13 +20,13 @@ class GeoIpMetricsFilter(
|
|||
private val client: HttpHandler
|
||||
) : Filter {
|
||||
|
||||
private val logger: Logger = LoggerFactory.getLogger(GeoIpMetricsFilter::class.java)
|
||||
private val LOGGER: Logger = LoggerFactory.getLogger(GeoIpMetricsFilter::class.java)
|
||||
|
||||
private lateinit var dbr: DatabaseReader
|
||||
|
||||
init {
|
||||
if (enableGeoIp) {
|
||||
logger.info("Initializing GeoIp support!")
|
||||
LOGGER.info { "Initializing GeoIp support!" }
|
||||
dbr = initDatabase()
|
||||
}
|
||||
}
|
||||
|
@ -39,17 +37,21 @@ class GeoIpMetricsFilter(
|
|||
}
|
||||
|
||||
return {
|
||||
val source = it.header("X-Forwarded-For") ?: it.source?.address
|
||||
source.apply {
|
||||
val sourceIp =
|
||||
it.headerValues("Forwarded")[0] // try Forwarded (rare but standard)
|
||||
?: it.headerValues("X-Forwarded-For")[0] // X-Forwarded-For (common but technically wrong)
|
||||
?: it.source?.address // source (in case of no proxying, or with proxy-protocol)
|
||||
|
||||
sourceIp.apply {
|
||||
try {
|
||||
val inetAddress = InetAddress.getByName(source)
|
||||
val inetAddress = InetAddress.getByName(sourceIp)
|
||||
if (!inetAddress.isLoopbackAddress && !inetAddress.isAnyLocalAddress) {
|
||||
val country = dbr.country(inetAddress)
|
||||
recordCountry(country.country.isoCode)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// do not disclose ip here, for privacy of logs
|
||||
logger.warn("Cannot resolve country from ip!")
|
||||
LOGGER.warn("Cannot resolve country from ip!")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +60,7 @@ class GeoIpMetricsFilter(
|
|||
}
|
||||
|
||||
private fun recordCountry(code: String) {
|
||||
logger.trace { "Registered hit for country code: $code" }
|
||||
LOGGER.trace { "Registered hit for country code: $code" }
|
||||
registry.counter(
|
||||
"requests_country_counts",
|
||||
"country", code
|
||||
|
@ -67,17 +69,26 @@ class GeoIpMetricsFilter(
|
|||
|
||||
private fun initDatabase(): DatabaseReader {
|
||||
val databaseFileDir = Files.createTempDirectory("mangadex-geoip")
|
||||
val downloadLocation = Files.createTempFile(databaseFileDir, "download", ".tar.gz")
|
||||
val databaseFile = Files.createTempFile(databaseFileDir, "geoip2_country", ".mmdb")
|
||||
|
||||
val geoIpDatabaseUri = "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=%s&suffix=tar.gz".format(license)
|
||||
val request = Request(Method.GET, geoIpDatabaseUri)
|
||||
|
||||
client(request).use {
|
||||
Files.write(downloadLocation, it.body.payload.array())
|
||||
val response = client(Request(Method.GET, geoIpDatabaseUri))
|
||||
if (response.status != Status.OK) {
|
||||
throw IllegalStateException("Couldn't download GeoIP 2 databse (status code from upstream: ${response.status})")
|
||||
}
|
||||
logger.info { "Downloaded GeoIp database at $downloadLocation" }
|
||||
|
||||
val databaseFile: Path = untarDatabase(databaseFileDir, downloadLocation)
|
||||
response.use {
|
||||
val archiveStream = TarArchiveInputStream(it.body.gunzippedStream().stream)
|
||||
var entry = archiveStream.nextTarEntry
|
||||
while (!entry.name.endsWith(".mmdb")) {
|
||||
LOGGER.trace { "Skip non-database file: ${entry.name}" }
|
||||
entry = archiveStream.nextTarEntry
|
||||
}
|
||||
|
||||
// reads only the current entry to its end
|
||||
val dbBytes = archiveStream.readAllBytes()
|
||||
Files.write(databaseFile, dbBytes)
|
||||
}
|
||||
|
||||
return DatabaseReader
|
||||
.Builder(databaseFile.toFile())
|
||||
|
@ -85,22 +96,4 @@ class GeoIpMetricsFilter(
|
|||
.build()
|
||||
}
|
||||
|
||||
private fun untarDatabase(cwd: Path, tarFile: Path): Path {
|
||||
val untarProcess = ProcessBuilder()
|
||||
.directory(cwd.toFile())
|
||||
.command("/usr/bin/env", "tar", "xfv", tarFile.toAbsolutePath().toString())
|
||||
.inheritIO()
|
||||
.start()
|
||||
|
||||
val retCode = untarProcess.waitFor()
|
||||
logger.info { "Tar return code: $retCode" }
|
||||
|
||||
return Files
|
||||
.walk(cwd)
|
||||
.filter { path: Path -> path.fileName.toString().endsWith(".mmdb") }
|
||||
.findAny()
|
||||
.orElseThrow()
|
||||
.toAbsolutePath()
|
||||
}
|
||||
|
||||
}
|
|
@ -326,7 +326,7 @@ fun getServer(
|
|||
).withFilter(
|
||||
ServerFilters.MicrometerMetrics.RequestTimer(registry, labeler = PostTransactionLabeler())
|
||||
).withFilter(
|
||||
GeoIpMetricsFilter(metricsSettings.enableGeoip, metricsSettings.geoipLicenseKey, registry, client)
|
||||
GeoIpMetricsFilter(metricsSettings.enableGeoip, metricsSettings.geoipLicenseKey, registry, apache)
|
||||
)
|
||||
)
|
||||
.asServer(Netty(remoteSettings.tls!!, serverSettings, statistics))
|
||||
|
|
Loading…
Reference in a new issue