func (s *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// println("Request to the remote service has been established")
	key := getURLParam(r, cfg.QueryCacheKey)
	if key == "" {
		// println("return because key was empty")
		w.WriteHeader(cfg.FailStatus)
		return
	}

	// we always need the Entry, so get it now
	entry := s.store.Get(key)

	if entry == nil && r.Method != methodPost {
		// if it's nil then means it never setted before
		// it doesn't exists, and client doesn't wants to
		// add a cache entry, so just return
		//
		// no delete action is valid
		// no get action is valid
		// no post action is requested
		w.WriteHeader(cfg.FailStatus)
		return
	}

	switch r.Method {
	case methodGet:
		{
			// get from the cache and send to client
			res, ok := entry.Response()
			if !ok {
				// entry exists but it has been expired
				// return
				w.WriteHeader(cfg.FailStatus)
				return
			}

			// entry exists and response is valid
			// send it to the client
			w.Header().Set(cfg.ContentTypeHeader, res.ContentType())
			w.WriteHeader(res.StatusCode())
			w.Write(res.Body())
		}
	case methodPost:
		{
			// save a new cache entry if entry ==nil or
			// update an existing if entry !=nil

			body, err := ioutil.ReadAll(r.Body)
			if err != nil || len(body) == 0 {
				// println("body's request was empty, return fail")
				w.WriteHeader(cfg.FailStatus)
				return
			}

			statusCode, _ := getURLParamInt(r, cfg.QueryCacheStatusCode)
			contentType := getURLParam(r, cfg.QueryCacheContentType)

			// now that we have the information
			// we want to see if this is a totally new cache entry
			// or just update an existing one with the new information
			// (an update can change the status code, content type
			//     and ofcourse the body and expiration time by header)

			if entry == nil {
				// get the information by its url
				// println("we have a post request method, let's save a cached entry ")
				// get the cache expiration via url param
				expirationSeconds, err := getURLParamInt64(r, cfg.QueryCacheDuration)
				// get the body from the requested body
				// get the expiration from the "cache-control's maxage" if no url param is setted
				if expirationSeconds <= 0 || err != nil {
					expirationSeconds = int64(nethttp.GetMaxAge(r)().Seconds())
				}
				// if not setted then try to get it via
				if expirationSeconds <= 0 {
					expirationSeconds = int64(cfg.MinimumCacheDuration.Seconds())
				}

				cacheDuration := time.Duration(expirationSeconds) * time.Second

				// store by its url+the key in order to be unique key among different servers with the same paths
				s.store.Set(key, statusCode, contentType, body, cacheDuration)
			} else {
				// update an existing one and change its duration  based on the header
				// (if > existing duration)
				entry.Reset(statusCode, contentType, body, nethttp.GetMaxAge(r))
			}

			w.WriteHeader(cfg.SuccessStatus)
		}
	case methodDelete:
		{
			// remove the entry entirely from the cache
			// manually DELETE cache should remove this entirely
			// no just invalidate it
			s.store.Remove(key)
			w.WriteHeader(cfg.SuccessStatus)
		}
	default:
		w.WriteHeader(cfg.FailStatus)
	}

}
func (s *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	
	key := getURLParam(r, cfg.QueryCacheKey)
	if key == "" {
		
		w.WriteHeader(cfg.FailStatus)
		return
	}

	
	entry := s.store.Get(key)

	if entry == nil && r.Method != methodPost {
		
		
		
		
		
		
		
		w.WriteHeader(cfg.FailStatus)
		return
	}

	switch r.Method {
	case methodGet:
		{
			
			res, ok := entry.Response()
			if !ok {
				
				
				w.WriteHeader(cfg.FailStatus)
				return
			}

			
			
			w.Header().Set(cfg.ContentTypeHeader, res.ContentType())
			w.WriteHeader(res.StatusCode())
			w.Write(res.Body())
		}
	case methodPost:
		{
			
			

			body, err := ioutil.ReadAll(r.Body)
			if err != nil || len(body) == 0 {
				
				w.WriteHeader(cfg.FailStatus)
				return
			}

			statusCode, _ := getURLParamInt(r, cfg.QueryCacheStatusCode)
			contentType := getURLParam(r, cfg.QueryCacheContentType)

			
			
			
			
			

			if entry == nil {
				
				
				
				expirationSeconds, err := getURLParamInt64(r, cfg.QueryCacheDuration)
				
				
				if expirationSeconds <= 0 || err != nil {
					expirationSeconds = int64(nethttp.GetMaxAge(r)().Seconds())
				}
				
				if expirationSeconds <= 0 {
					expirationSeconds = int64(cfg.MinimumCacheDuration.Seconds())
				}

				cacheDuration := time.Duration(expirationSeconds) * time.Second

				
				s.store.Set(key, statusCode, contentType, body, cacheDuration)
			} else {
				
				
				entry.Reset(statusCode, contentType, body, nethttp.GetMaxAge(r))
			}

			w.WriteHeader(cfg.SuccessStatus)
		}
	case methodDelete:
		{
			
			
			
			s.store.Remove(key)
			w.WriteHeader(cfg.SuccessStatus)
		}
	default:
		w.WriteHeader(cfg.FailStatus)
	}

}
func ( s * Handler ) ServeHTTP ( w http . ResponseWriter , r * http . Request ) { // println("Request to the remote service has been established") key := getURLParam ( r , cfg . QueryCacheKey ) if key == " " { // println("return because key was empty") w . WriteHeader ( cfg . FailStatus ) return } // we always need the Entry, so get it now entry := s . store . Get ( key ) if entry == nil && r . Method != methodPost { // if it's nil then means it never setted before // it doesn't exists, and client doesn't wants to // add a cache entry, so just return // // no delete action is valid // no get action is valid // no post action is requested w . WriteHeader ( cfg . FailStatus ) return } switch r . Method { case methodGet : { // get from the cache and send to client res , ok := entry . Response ( ) if ! ok { // entry exists but it has been expired // return w . WriteHeader ( cfg . FailStatus ) return } // entry exists and response is valid // send it to the client w . Header ( ) . Set ( cfg . ContentTypeHeader , res . ContentType ( ) ) w . WriteHeader ( res . StatusCode ( ) ) w . Write ( res . Body ( ) ) } case methodPost : { // save a new cache entry if entry ==nil or // update an existing if entry !=nil body , err := ioutil . ReadAll ( r . Body ) if err != nil || len ( body ) == 0 { // println("body's request was empty, return fail") w . WriteHeader ( cfg . FailStatus ) return } statusCode , _ := getURLParamInt ( r , cfg . QueryCacheStatusCode ) contentType := getURLParam ( r , cfg . QueryCacheContentType ) // now that we have the information // we want to see if this is a totally new cache entry // or just update an existing one with the new information // (an update can change the status code, content type //     and ofcourse the body and expiration time by header) if entry == nil { // get the information by its url // println("we have a post request method, let's save a cached entry ") // get the cache expiration via url param expirationSeconds , err := getURLParamInt64 ( r , cfg . QueryCacheDuration ) // get the body from the requested body // get the expiration from the "cache-control's maxage" if no url param is setted if expirationSeconds <= 0 || err != nil { expirationSeconds = int64 ( nethttp . GetMaxAge ( r ) ( ) . Seconds ( ) ) } // if not setted then try to get it via if expirationSeconds <= 0 { expirationSeconds = int64 ( cfg . MinimumCacheDuration . Seconds ( ) ) } cacheDuration := time . Duration ( expirationSeconds ) * time . Second // store by its url+the key in order to be unique key among different servers with the same paths s . store . Set ( key , statusCode , contentType , body , cacheDuration ) } else { // update an existing one and change its duration  based on the header // (if > existing duration) entry . Reset ( statusCode , contentType , body , nethttp . GetMaxAge ( r ) ) } w . WriteHeader ( cfg . SuccessStatus ) } case methodDelete : { // remove the entry entirely from the cache // manually DELETE cache should remove this entirely // no just invalidate it s . store . Remove ( key ) w . WriteHeader ( cfg . SuccessStatus ) } default : w . WriteHeader ( cfg . FailStatus ) } }
// ServeHTTP serves the cache Service to the outside world,
// it is used only when you want to achieve something like horizontal scaling
// it parses the request and tries to return the response with the cached body of the requested cache key
// server-side function
ServeHTTP serves the cache Service to the outside world it is used only when you want to achieve something like horizontal scaling it parses the request and tries to return the response with the cached body of the requested cache key server - side function