package modules import java.security.MessageDigest import java.time.Instant import java.time.temporal.ChronoUnit import java.util.{Date, Optional} import javax.inject.Inject import enums.Status import models.JedisRequest import org.apache.xerces.impl.dv.util.Base64 import play.api.Configuration import play.i18n.Lang import play.api.libs.concurrent.Execution.Implicits.defaultContext import play.api.mvc._ import play.libs.Json import play.mvc.Http import services.{JedisService, ResponseService} import scala.concurrent.Future class RequestRepeatingFilter @Inject()(jedisService: JedisService, configuration: Configuration, responseService: ResponseService) extends Filter { val MIN_REPEAT_TIME_ALLOWED: String = "requestMinRepeatTimeAllowed" override def apply(nextFilter: RequestHeader => Future[Result]) (requestHeader: RequestHeader): Future[Result] = { val timeTillNextRequestAllowed = configuration.getLong(MIN_REPEAT_TIME_ALLOWED) val requestString = requestHeader.method + requestHeader.path + requestHeader.headers.toSimpleMap.toString() val md5RequestString = "request." + Base64.encode(MessageDigest.getInstance("MD5").digest(requestString.getBytes)) val redisRequestOptional: Optional[String] = jedisService.get(md5RequestString) if (redisRequestOptional.isPresent) { val redisRequest: JedisRequest = Json.fromJson(Json.parse(redisRequestOptional.get), classOf[JedisRequest]) if (!redisRequest.isExecuted) { // 202 nextFilter(requestHeader).map { result => play.Logger.error("202") val language: play.api.i18n.Lang = if (requestHeader.acceptLanguages.isEmpty) play.api.i18n.Lang.defaultLang else play.api.i18n.Lang.preferred(requestHeader.acceptLanguages) Future.successful(responseService.status(Status.ACCEPTED, new Lang(language))) } } else if (redisRequest.getLastExecuted.after(Date.from(Instant.now.minus(timeTillNextRequestAllowed.get, ChronoUnit.SECONDS)))) { //429 play.Logger.error("429") nextFilter(requestHeader).map { result => val language: play.api.i18n.Lang = if (requestHeader.acceptLanguages.isEmpty) play.api.i18n.Lang.defaultLang else play.api.i18n.Lang.preferred(requestHeader.acceptLanguages) Future.successful(responseService.status(Status.TOO_MANY_REQUESTS, new Lang(language))) } } } play.Logger.error("doing it again") upsertRedisRequest(md5RequestString, completed = false) nextFilter(requestHeader).map { result => upsertRedisRequest(md5RequestString, completed = true) result } } private def upsertRedisRequest(md5Hash: String, completed: Boolean) { val request: JedisRequest = new JedisRequest(true, Date.from(Instant.now)) jedisService.set(md5Hash, Json.toJson(request).toString) } }