11package me.snoty.integration.contrib.autoscout.api
22
3+ import io.github.oshai.kotlinlogging.KotlinLogging
34import io.ktor.client.*
45import io.ktor.client.request.*
6+ import io.ktor.http.*
57import kotlinx.serialization.json.Json
68import kotlinx.serialization.json.jsonObject
79import me.snoty.integration.contrib.autoscout.model.AutoscoutListing
@@ -16,11 +18,40 @@ interface AutoscoutAPI {
1618}
1719
1820@Single
19- class AutoscoutAPIImpl (private val httpClient : HttpClient , private val json : Json ) : AutoscoutAPI, KoinComponent {
21+ class AutoscoutAPIImpl (httpClient : HttpClient , private val json : Json ) : AutoscoutAPI, KoinComponent {
22+ private val noRedirectClient = httpClient.config {
23+ followRedirects = false
24+ // failures are handled explicitly
25+ expectSuccess = false
26+ }
27+
28+ val logger = KotlinLogging .logger {}
29+
2030 override suspend fun fetchListing (url : String ): AutoscoutListing ? {
2131 val mappedUrl = parseAutoscoutUrl(url)
2232
23- val response = httpClient.get(mappedUrl)
33+ val response = noRedirectClient.get(mappedUrl)
34+
35+ fun logListingExpired () {
36+ logger.warn { " Listing $url is expired" }
37+ }
38+
39+ when (response.status) {
40+ HttpStatusCode .MovedPermanently -> {
41+ val location = response.headers[HttpHeaders .Location ] ? : throw IllegalArgumentException (" Redirect without a Location" )
42+ if (location.startsWith(" /lst/" )) {
43+ logListingExpired()
44+ return null
45+ }
46+ throw IllegalArgumentException (" Invalid redirect location: $location " )
47+ }
48+ HttpStatusCode .NotFound , HttpStatusCode .Gone -> {
49+ logListingExpired()
50+ return null
51+ }
52+ HttpStatusCode .OK -> Unit
53+ else -> throw IllegalArgumentException (" Invalid response status: ${response.status} " )
54+ }
2455
2556 val props = response.parseNextPageProps(json)
2657 val advertDetails = props.getOrThrow(" listingDetails" ).jsonObject
0 commit comments