1
#pragma once
2

            
3
#include <memory>
4
#include <tuple>
5

            
6
#include "envoy/extensions/http/stateful_session/header/v3/header.pb.h"
7
#include "envoy/http/stateful_session.h"
8

            
9
#include "source/common/common/base64.h"
10
#include "source/common/http/headers.h"
11
#include "source/common/http/utility.h"
12

            
13
namespace Envoy {
14
namespace Extensions {
15
namespace Http {
16
namespace StatefulSession {
17
namespace Header {
18

            
19
using HeaderBasedSessionStateProto =
20
    envoy::extensions::http::stateful_session::header::v3::HeaderBasedSessionState;
21

            
22
class HeaderBasedSessionStateFactory : public Envoy::Http::SessionStateFactory {
23
public:
24
  class SessionStateImpl : public Envoy::Http::SessionState {
25
  public:
26
    SessionStateImpl(absl::optional<std::string> address,
27
                     const HeaderBasedSessionStateFactory& factory)
28
11
        : upstream_address_(std::move(address)), factory_(factory) {}
29

            
30
11
    absl::optional<absl::string_view> upstreamAddress() const override { return upstream_address_; }
31
    bool onUpdate(absl::string_view host_address, Envoy::Http::ResponseHeaderMap& headers) override;
32

            
33
  private:
34
    absl::optional<std::string> upstream_address_;
35
    const HeaderBasedSessionStateFactory& factory_;
36
  };
37

            
38
  HeaderBasedSessionStateFactory(const HeaderBasedSessionStateProto& config);
39

            
40
11
  Envoy::Http::SessionStatePtr create(Envoy::Http::RequestHeaderMap& headers) const override {
41
11
    return std::make_unique<SessionStateImpl>(parseAddress(headers), *this);
42
11
  }
43

            
44
private:
45
11
  absl::optional<std::string> parseAddress(const Envoy::Http::RequestHeaderMap& headers) const {
46
11
    auto hdr = headers.get(Envoy::Http::LowerCaseString(name_));
47
11
    if (hdr.empty()) {
48
3
      return absl::nullopt;
49
3
    }
50

            
51
8
    auto header_value = hdr[0]->value().getStringView();
52
8
    std::string address = Envoy::Base64::decode(header_value);
53
8
    return !address.empty() ? absl::make_optional(std::move(address)) : absl::nullopt;
54
11
  }
55

            
56
5
  const Envoy::Http::LowerCaseString& getHeaderName() const { return name_; }
57

            
58
  const Envoy::Http::LowerCaseString name_;
59
};
60

            
61
} // namespace Header
62
} // namespace StatefulSession
63
} // namespace Http
64
} // namespace Extensions
65
} // namespace Envoy