SCB-1478 support API gateway (#73)

diff --git a/README.md b/README.md
index 567b03a..9da0058 100644
--- a/README.md
+++ b/README.md
@@ -14,11 +14,11 @@
 and use mesher to make other service join to the same system.
 - flexible: you can develop and customize your own service mesh
 - OS: support both linux and windows OS, which means you can govern your services writen in .net with java, go etc.
-
+- API gateway: mesher is able to run as a independent edge service and manage ingress traffic.
 # Features
 - Build on top of go micro service framework: so that mesher has all of features of 
 [go chassis](https://github.com/go-chassis/go-chassis),a high flexible go micro service framework. 
-you can custom your own service mesh by extending lots of components.
+you can custom your own service mesh and API gateway by extending lots of components.
 - Admin API:Listen on an isolated port, expose useful runtime information and metrics.
 - support protocols: http and grpc
 - No IP tables forwarding: Mesher leverage 
@@ -59,7 +59,6 @@
 - docker image name: servicecomb/mesher-sidecar:latest
 
 # Documentations
-# Documentations
 You can see more documentations in [here](https://mesher.readthedocs.io/en/latest/), 
 this online doc is for latest version of mesher, if you want to see your version's doc,
 follow [here](docs/README.md) to generate it in local
diff --git a/cmd/mesher/mesher.go b/cmd/mesher/mesher.go
index a1a28a5..007ff20 100644
--- a/cmd/mesher/mesher.go
+++ b/cmd/mesher/mesher.go
@@ -26,12 +26,13 @@
 	_ "github.com/apache/servicecomb-mesher/proxy/protocol/dubbo/client/chassis"
 	_ "github.com/apache/servicecomb-mesher/proxy/protocol/dubbo/server"
 	_ "github.com/apache/servicecomb-mesher/proxy/protocol/dubbo/simpleRegistry"
-
-	_ "github.com/go-chassis/go-chassis/configcenter" //use config center
+	// config server
+	_ "github.com/go-chassis/go-chassis-config/servicecombkie"
 	//protocols
 	_ "github.com/apache/servicecomb-mesher/proxy/protocol/grpc"
 	_ "github.com/apache/servicecomb-mesher/proxy/protocol/http"
-
+	//ingress rule fetcher
+	_ "github.com/apache/servicecomb-mesher/proxy/ingress/servicecomb"
 	"github.com/apache/servicecomb-mesher/proxy/server"
 
 	_ "github.com/apache/servicecomb-mesher/proxy/pkg/egress/archaius"
diff --git a/docs/configuration.rst b/docs/configuration.rst
index 791543c..eaad50b 100644
--- a/docs/configuration.rst
+++ b/docs/configuration.rst
@@ -10,3 +10,4 @@
    configurations/admin
    configurations/health
    configurations/destination_resolver
+   configurations/edge
diff --git a/docs/configurations/cli.md b/docs/configurations/cli.md
index 0fe6811..38c646e 100644
--- a/docs/configurations/cli.md
+++ b/docs/configurations/cli.md
@@ -13,7 +13,7 @@
 
 
 **--mode**
->*(optional, string)* mesher has 2 work mode, sidecar and per-host, default is sidecar
+>*(optional, string)* mesher has 2 work mode, sidecar and edge, default is sidecar
 
 
 **--service-ports**
diff --git a/docs/configurations/edge.md b/docs/configurations/edge.md
new file mode 100644
index 0000000..9076689
--- /dev/null
+++ b/docs/configurations/edge.md
@@ -0,0 +1,78 @@
+# API gateway
+mesher is able to work as a API gateway to mange traffic,to run mesher as an API gateway
+```shell
+mesher --config=mesher.yaml --mode edge
+```
+the ingress rule is in mesher.yaml
+
+### Options
+
+**mesher.ingress.type**
+>*(optional, string)* default is servicecomb, it reads servicecomb ingress rule. 
+>it is a plugin, you can custom your own implementation
+
+
+**mesher.ingress.rule.http**
+>*(optional, string)* rule about how to forward http traffic. it holds a yaml content as rule.
+
+below explain the content, the rule list is like a filter, all the request will go through this rule list until match one rule.
+
+**apiPath**
+>*(required, string)* if request's url match this, it will use this rule
+
+**host**
+>*(optional, string)* if request HOST match this, mesher will use this rule, it can be empty, 
+>if you set both host and apiPath, the request's host and api path must match them at the same time
+>
+**service.name**
+>*(required, string)* target backend service name in registry service(like ServiceComb service center)
+>
+**service.redirectPath**
+>*(optional, string)* by default, mesher use original request's url
+>
+**service.port.value**
+>*(optional, string)* if you use java chassis or go chassis to develop backend service, no need to set it. 
+>but if your backend service use mesher-sidecar, you must give your service port here.
+>
+### example
+```yaml
+mesher:
+  ingress:
+    type: servicecomb
+    rule:
+      http: |
+        - host: example.com
+          apiPath: /some/api
+          service:
+            name: example
+            redirectPath: /another/api
+            port:
+              name: http-legacy
+              value: 8080
+        - apiPath: /some/api
+          service:
+            name: Server
+            port:
+              name: http
+              value: 8080
+```
+
+
+### Enable TLS
+generate private key
+```sh
+openssl genrsa -out server.key 2048
+```
+sign cert with private key
+```shell script
+openssl req -new -x509 -key server.key -out server.crt -days 3650
+```
+set file path in chassis.yaml
+```yaml
+ssl:
+  mesher-edge.rest.Provider.certFile: server.crt
+  mesher-edge.rest.Provider.keyFile: server.key
+```
+
+To know advanced feature about TLS configuration, check 
+https://docs.go-chassis.com/user-guides/tls.html
\ No newline at end of file
diff --git a/docs/development.rst b/docs/development.rst
new file mode 100644
index 0000000..079de99
--- /dev/null
+++ b/docs/development.rst
@@ -0,0 +1,20 @@
+Development guides
+=========================
+mesher is an out of box service mesh and API gateway component,
+you can use them by simply setting configuration files.
+But some of user still need to customize a service mesh or API gateway.
+For example:
+
+- API gateway need to query account system and do the authentication and authorization.
+- mesher need to access cloud provider API
+- mesher use customized control panel
+- mesher use customized config server
+
+
+.. toctree::
+   :maxdepth: 4
+   :glob:
+
+   development/handler-chain
+   development/cloud-provider
+   development/build
diff --git a/docs/development/build.md b/docs/development/build.md
new file mode 100644
index 0000000..0454d44
--- /dev/null
+++ b/docs/development/build.md
@@ -0,0 +1,7 @@
+# Build mesher
+you need to build and release your mesher after the customization
+
+### Build binary
+you can refer to build/build_proxy to see how we build mesher binary and docker image.
+
+build/docker/proxy/Dockerfile is a example about how to make a docker image
\ No newline at end of file
diff --git a/docs/development/cloud-provider.md b/docs/development/cloud-provider.md
new file mode 100644
index 0000000..f464ac8
--- /dev/null
+++ b/docs/development/cloud-provider.md
@@ -0,0 +1,33 @@
+# Cloud Provider
+By default Mesher do not support any cloud provider.
+But there is plugin that helps mesher to do it.
+
+### Huawei Cloud 
+Mesher is able to use huawei cloud ServiceComb engine. 
+#### Access ServiceComb Engine API
+import auth in cmd/mesher/mesher.go
+```go
+import _ "github.com/huaweicse/auth/adaptor/gochassis"
+```
+
+it will sign all requests between mesher to ServiceComb Engine.
+
+#### Use Config Center to manage configuration
+Mesher use servicecomb-kie as config server, 
+```go
+_ "github.com/go-chassis/go-chassis-config/servicecombkie"
+```
+when you need to use ServiceComb Engine, you must replace this line. 
+import config center in cmd/mesher/mesher.go.
+```go
+_ "github.com/go-chassis/go-chassis-config/configcenter"
+```
+set the config center in chassis.yaml
+```yaml
+  config:
+    client:
+      serverUri: https://xxx #endpoint of servicecomb engine
+      refreshMode: 1 # 1: only pull config.
+      refreshInterval: 30 # unit is second
+      type: config_center
+```
\ No newline at end of file
diff --git a/docs/development/handler-chain.md b/docs/development/handler-chain.md
new file mode 100644
index 0000000..4960583
--- /dev/null
+++ b/docs/development/handler-chain.md
@@ -0,0 +1,42 @@
+# Handler chain
+all the traffic will go through the handler chain.
+A chain is composite of handlers, each handler has a particular logic.
+Mesher also has a lots of feature working in chain, like route management, circuit breaking, rate-limiting.
+In Summary, handler is the middle ware between client and servers, 
+it is useful, when you want to add authorization to intercept illegal requests.
+
+### How to write a handler
+https://docs.go-chassis.com/dev-guides/how-to-implement-handler.html
+
+### How to use it in handler chain
+in chassis.yaml add your handler name in chain configuration.
+as side car and API gateway, mesher's chain has different meaning.
+
+For example, running as mesher-sidecar, service A call another service B, 
+outgoing chain process all the service A requests before remote call, 
+incoming chain process all the requests from service A, before access to service B API. 
+
+In summary outgoing chain works when a service attempt to call other services, 
+incoming chain works when other services call this service
+```yaml
+  handler:
+    chain:
+      Consumer:
+        # if a service call other service, it go through this chain, loadbalance and transport is must 
+        outgoing: router, bizkeeper-consumer, loadbalance, transport
+      Provider:
+        incoming: ratelimiter-provider
+```
+
+running as API gateway, 
+incoming chain process all the requests from the external network, 
+outgoing chain process all the the request between API gateway and backend services
+```yaml
+  handler:
+    chain:
+      Consumer:
+        #loadbalance and transport is must 
+        outgoing: router, bizkeeper-consumer, loadbalance, transport
+      Provider:
+        incoming: ratelimiter-provider
+```
\ No newline at end of file
diff --git a/docs/index.rst b/docs/index.rst
index 17e0a0c..09187fc 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -13,6 +13,7 @@
    intro
    get-started
    configuration
+   development
    protocols
    istio-guides
    sidecar
diff --git a/examples/edge/conf/chassis.yaml b/examples/edge/conf/chassis.yaml
new file mode 100644
index 0000000..0ab8bd4
--- /dev/null
+++ b/examples/edge/conf/chassis.yaml
@@ -0,0 +1,78 @@
+---
+cse:
+  protocols:
+    http:
+      listenAddress: 127.0.0.1:30101
+    rest-admin:
+      listenAddress: 127.0.0.1:30102 # listen addr use to adminAPI
+  service:
+    registry:
+      address: http://127.0.0.1:30100 # uri of service center
+      #address: https://cse.cn-north-1.myhuaweicloud.com:443 # uri of service center
+      scope: full #set full to be able to discover other app's service
+      watch: false # set if you want to watch instance change event
+      autoIPIndex: true # set to true if u want to resolve source IP to micro service
+#    config:
+#      client:
+#        serverUri: https://127.0.0.1:30110 #uri of config center
+#        type: servicecomb-kie
+#        refreshMode: 1 # 1: only pull config.
+#        refreshInterval: 30 # unit is second
+  #  monitor: #Send monitoring data to CSE monitor Server
+  #    client:
+  #      serverUri: https://cse.cn-north-1.myhuaweicloud.com:443   # monitor server url
+  handler:
+    chain:
+      Consumer:
+        outgoing:  router,bizkeeper-consumer,loadbalance,tracing-consumer,transport #consumer handlers
+      Provider:
+        incoming:   tracing-provider #provider handlers
+#  loadbalance:
+#    strategy:
+#      name: RoundRobin  # Random|RoundRobin|SessionStickiness
+#    retryEnabled: false # if there is error, retry request or not
+#    retryOnNext: 2      # times to switch to another instance based on strategy
+#    retryOnSame: 3      # times to retry on the same instance
+#    backoff:            # backoff policy of retried request
+#      kind: constant    # jittered/constant/zero
+#      MinMs: 200        # millisecond, Minimum duration to backoff
+#      MaxMs: 400        # millisecond, Maximum duration to backoff
+## circuit breaker configurations
+#  isolation:
+#    Consumer:
+#      timeout:
+#        enabled: true
+#      timeoutInMilliseconds: 1000
+#      maxConcurrentRequests: 100
+#  circuitBreaker:
+#    Consumer:
+#      enabled: true
+#      forceOpen: false
+#      forceClosed: false
+#      sleepWindowInMilliseconds: 10000
+#      requestVolumeThreshold: 20
+#      errorThresholdPercentage: 50
+#  fallback:
+#    Consumer:
+#      enabled: true
+#      maxConcurrentRequests: 20
+#  fallbackpolicy:
+#    Consumer:
+#      policy: throwexception
+
+## Mesher TLS is base on Go Chassis TLS config
+ssl:
+#  mesher-edge.rest.Provider.cipherPlugin: default
+#  mesher-edge.rest.Provider.verifyPeer: false
+#  mesher-edge.rest.Provider.cipherSuits: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+#  mesher-edge.rest.Provider.protocol: TLSv1.2
+#  mesher-edge.rest.Provider.caFile:
+  mesher-edge.rest.Provider.certFile: server.crt
+  mesher-edge.rest.Provider.keyFile: server.key
+#  mesher-edge.rest.Provider.certPwdFile:
+
+#tracing:
+#  enabled: true #enable distribution tracing
+#  collectorType: zipkin       #zipkin: Send tracing info to zipkin server
+#                              #namedPipe: Write tracing info to linux named pipe.
+#  collectorTarget: http://localhost:9411/api/v1/spans #If the collectorType is "zipkin", the target is a zipkin server url, if the collecterType is "file" or "namedPipe", the target is a file path.
diff --git a/examples/edge/conf/mesher.yaml b/examples/edge/conf/mesher.yaml
new file mode 100644
index 0000000..55aa97f
--- /dev/null
+++ b/examples/edge/conf/mesher.yaml
@@ -0,0 +1,52 @@
+## Router rules and fault injection rules are moved to router.yaml
+#plugin:
+#  destinationResolver:
+#    http: host # how to turn host to destination name. default to service name,
+
+admin: #admin API
+  goRuntimeMetrics : true # enable metrics
+  enable: true
+
+## enable pprof to profile mesher runtime
+#pprof:
+#  enable: false
+
+
+# this health check will ping local service port to check if service is still alive, if service can not reachable, mesher
+# will update status to OUT_OF_SERVICE in service center
+#localHealthCheck:
+#  - port: 8080
+#    uri: /health
+#    interval: 30s
+#    match:
+#      status: 200
+#      body: ok
+
+
+mesher:
+  ingress:
+    type: servicecomb
+    rule:
+      http: |
+        - host: example.com
+          limit: 30
+          apiPath: /some/api
+          service:
+            name: example
+            redirectPath: /another/api
+            port:
+              name: http-legacy
+              value: 8080
+        - apiPath: /sayerror/api
+          service:
+            name: Server
+            redirectPath: /sayerror
+            port:
+              name: http
+              value: 8080
+        - apiPath: /some/api
+          service:
+            name: Server
+            port:
+              name: http
+              value: 8080
\ No newline at end of file
diff --git a/examples/edge/conf/microservice.yaml b/examples/edge/conf/microservice.yaml
new file mode 100644
index 0000000..8103479
--- /dev/null
+++ b/examples/edge/conf/microservice.yaml
@@ -0,0 +1,3 @@
+service_description:
+  name: mesher-edge
+  version: 0.0.1
diff --git a/go.mod b/go.mod
index b0bb0ae..addfe9b 100644
--- a/go.mod
+++ b/go.mod
@@ -2,20 +2,22 @@
 
 require (
 	github.com/Shopify/toxiproxy v2.1.3+incompatible // indirect
+	github.com/apache/servicecomb-kie v0.1.0 // indirect
 	github.com/emicklei/go-restful-swagger12 v0.0.0-20170926063155-7524189396c6 // indirect
 	github.com/envoyproxy/go-control-plane v0.6.0
-	github.com/ghodss/yaml v1.0.0 // indirect
+	github.com/ghodss/yaml v1.0.0
 	github.com/go-chassis/foundation v0.0.0-20190621030543-c3b63f787f4c
 	github.com/go-chassis/go-archaius v0.20.0
-	github.com/go-chassis/go-chassis v1.6.1
+	github.com/go-chassis/go-chassis v1.7.1-0.20190903133217-e4a22c998fe1
+	github.com/go-chassis/go-chassis-config v0.10.0
 	github.com/go-chassis/gohessian v0.0.0-20180702061429-e5130c25af55
-	github.com/go-mesh/openlogging v1.0.0
+	github.com/go-logfmt/logfmt v0.4.0 // indirect
+	github.com/go-mesh/openlogging v1.0.1-0.20181205082104-3d418c478b2d
 	github.com/gogo/googleapis v1.1.0 // indirect
 	github.com/gogo/protobuf v1.2.0
 	github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf // indirect
 	github.com/imdario/mergo v0.3.6 // indirect
 	github.com/lyft/protoc-gen-validate v0.0.11 // indirect
-	github.com/onsi/gomega v1.4.2 // indirect
 	github.com/patrickmn/go-cache v2.1.0+incompatible
 	github.com/prometheus/client_golang v0.9.1
 	github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f
@@ -23,7 +25,6 @@
 	github.com/stretchr/testify v1.3.0
 	github.com/uber-go/atomic v1.3.2 // indirect
 	github.com/urfave/cli v1.20.1-0.20181029213200-b67dcf995b6a
-	go.uber.org/atomic v1.3.2 // indirect
 	golang.org/x/net v0.0.0-20190311183353-d8887717615a
 	golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 // indirect
 	google.golang.org/grpc v1.16.0
diff --git a/proxy/bootstrap/bootstrap.go b/proxy/bootstrap/bootstrap.go
index 431613c..09b5872 100644
--- a/proxy/bootstrap/bootstrap.go
+++ b/proxy/bootstrap/bootstrap.go
@@ -82,20 +82,21 @@
 
 //DecideMode get config mode
 func DecideMode() error {
-	runtime.Mode = cmd.Configs.Mode
-	openlogging.GetLogger().Info("Running as " + runtime.Mode)
+	runtime.Role = cmd.Configs.Role
+	openlogging.GetLogger().Info("Running as " + runtime.Role)
 	return nil
 }
 
 //RegisterFramework registers framework
 func RegisterFramework() {
-	if framework := metadata.NewFramework(); cmd.Configs.Mode == common.ModeSidecar {
-		version := GetVersion()
+	version := GetVersion()
+	if framework := metadata.NewFramework(); cmd.Configs.Role == common.RoleSidecar {
 		framework.SetName("Mesher")
 		framework.SetVersion(version)
 		framework.SetRegister("SIDECAR")
-	} else if cmd.Configs.Mode == common.ModePerHost {
+	} else {
 		framework.SetName("Mesher")
+		framework.SetVersion(version)
 	}
 }
 
diff --git a/proxy/cmd/cmd.go b/proxy/cmd/cmd.go
index 5fe043a..b0bb140 100644
--- a/proxy/cmd/cmd.go
+++ b/proxy/cmd/cmd.go
@@ -33,7 +33,7 @@
 //ConfigFromCmd store cmd params
 type ConfigFromCmd struct {
 	ConfigFile        string
-	Mode              string
+	Role              string
 	LocalServicePorts string
 	PortsMap          map[string]string
 }
@@ -54,10 +54,10 @@
 		},
 		cli.StringFlag{
 			Name:  "mode",
-			Value: common.ModeSidecar,
-			Usage: fmt.Sprintf("mesher running mode [ %s|%s|%s ]",
-				common.ModePerHost, common.ModeSidecar, common.ModeIngress),
-			Destination: &Configs.Mode,
+			Value: common.RoleSidecar,
+			Usage: fmt.Sprintf("mesher role [ %s|%s|%s ]",
+				common.RolePerHost, common.RoleSidecar, common.RoleEdge),
+			Destination: &Configs.Role,
 		},
 		cli.StringFlag{
 			Name:        "service-ports",
diff --git a/proxy/common/common.go b/proxy/common/common.go
index 4eaf3b0..04b536f 100644
--- a/proxy/common/common.go
+++ b/proxy/common/common.go
@@ -32,14 +32,14 @@
 //ComponentName is contant for component name
 const ComponentName = "mesher"
 
-//ModeSidecar is constant for side car mode
-const ModeSidecar = "sidecar"
+//RoleSidecar is constant for side car mode
+const RoleSidecar = "sidecar"
 
-//ModeIngress run as a api gateway, or ingress in k8s
-const ModeIngress = "ingress"
+//RoleEdge run as a edge service, or ingress in k8s
+const RoleEdge = "edge"
 
-//ModePerHost is constant for side car mode
-const ModePerHost = "per-host"
+//RolePerHost is constant for side car mode
+const RolePerHost = "per-host"
 
 //Constants for env specific addr and service ports
 const (
diff --git a/proxy/config/config.go b/proxy/config/config.go
index 1f797be..ac3143d 100644
--- a/proxy/config/config.go
+++ b/proxy/config/config.go
@@ -18,6 +18,10 @@
 package config
 
 import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
+
 	"github.com/apache/servicecomb-mesher/proxy/cmd"
 	"github.com/apache/servicecomb-mesher/proxy/common"
 	"github.com/go-chassis/go-archaius"
@@ -28,9 +32,6 @@
 	"github.com/go-chassis/go-chassis/pkg/util/fileutil"
 	"github.com/go-mesh/openlogging"
 	"gopkg.in/yaml.v2"
-	"io/ioutil"
-	"os"
-	"path/filepath"
 )
 
 //Constant for mesher conf file
@@ -88,6 +89,16 @@
 //Init reads config and initiates
 func Init() error {
 	mesherConfig = &MesherConfig{}
+	egressConfig = &EgressConfig{}
+	p, err := GetConfigFilePath(ConfFile)
+	if err != nil {
+		return err
+	}
+	err = archaius.AddFile(p)
+	if err != nil {
+		return err
+	}
+
 	contents, err := GetConfigContents(ConfFile)
 	if err != nil {
 		return err
@@ -96,7 +107,6 @@
 		return err
 	}
 
-	egressConfig = &EgressConfig{}
 	egressContents, err := GetConfigContents(EgressConfFile)
 	if err != nil {
 		return err
diff --git a/proxy/config/struct.go b/proxy/config/struct.go
index c551953..d4d5914 100644
--- a/proxy/config/struct.go
+++ b/proxy/config/struct.go
@@ -19,6 +19,7 @@
 
 //MesherConfig has all mesher config
 type MesherConfig struct {
+	Mesher      Mesher         `yaml:"mesher"`
 	PProf       *PProf         `yaml:"pprof"`
 	Plugin      *Plugin        `yaml:"plugin"`
 	Admin       Admin          `yaml:"admin"`
diff --git a/proxy/config/struct_ingress.go b/proxy/config/struct_ingress.go
new file mode 100644
index 0000000..0f90f7b
--- /dev/null
+++ b/proxy/config/struct_ingress.go
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package config
+
+import (
+	"github.com/go-chassis/foundation/string"
+	"gopkg.in/yaml.v2"
+)
+
+//Mesher is prefix
+type Mesher struct {
+	Ingress Ingress `yaml:"ingress"`
+}
+
+//Ingress hold rules and other settings
+type Ingress struct {
+	Rule map[string]string `yaml:"rule"`
+	Type string            `yaml:"type"`
+}
+
+//IngressRules is ingress rules slice
+type IngressRules []*IngressRule
+
+//Len return the length of rule
+func (r IngressRules) Len() int {
+	return len(r)
+}
+
+//Value return the rule
+func (r IngressRules) Value() []*IngressRule {
+	return r
+}
+
+//NewRules create a rule by raw data
+func NewRules(raw string) (*IngressRules, error) {
+	b := stringutil.Str2bytes(raw)
+	r := &IngressRules{}
+	err := yaml.Unmarshal(b, r)
+	return r, err
+}
+
+//IngressRule is a ingress rule
+type IngressRule struct {
+	Host    string  `yaml:"host"`
+	Limit   int     `yaml:"limit"`
+	APIPath string  `yaml:"apiPath"`
+	Service Service `yaml:"service"`
+}
+
+//Service is upstream info
+type Service struct {
+	Name         string            `yaml:"name"`
+	Tags         map[string]string `yaml:"tags"`
+	RedirectPath string            `yaml:"redirectPath"`
+	Port         Port              `yaml:"port"`
+}
+
+//Port is service port information
+type Port struct {
+	Name  string `yaml:"name"`
+	Value string `yaml:"value"`
+}
diff --git a/proxy/config/struct_ingress_test.go b/proxy/config/struct_ingress_test.go
new file mode 100644
index 0000000..22d268e
--- /dev/null
+++ b/proxy/config/struct_ingress_test.go
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package config_test
+
+import (
+	"github.com/apache/servicecomb-mesher/proxy/config"
+	"github.com/ghodss/yaml"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestNewRules(t *testing.T) {
+	b := []byte(`
+mesher:
+  ingress:
+    type: servicecomb
+    rule:
+      http: |
+        - host: example.com
+          limit: 30
+          apiPath: /some/api
+          service:
+            name: example
+            tags:
+              version: 1.0.0
+            redirectPath: /another/api
+            port:
+              name: http-legacy
+              value: 8080
+        - host: foo.com
+          apiPath: /some/api
+          service:
+            name: foo
+            tags:
+              version: 1.0.0
+            redirectPath: /another/api
+            port:
+              name: http
+              value: 8080
+`)
+	c := &config.MesherConfig{}
+	err := yaml.Unmarshal(b, c)
+	assert.NoError(t, err)
+	rules, err := config.NewRules(c.Mesher.Ingress.Rule["http"])
+	assert.NoError(t, err)
+	assert.Equal(t, 2, rules.Len())
+}
diff --git a/proxy/ingress/ingress.go b/proxy/ingress/ingress.go
new file mode 100644
index 0000000..916c4c2
--- /dev/null
+++ b/proxy/ingress/ingress.go
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ingress
+
+import (
+	"errors"
+	"fmt"
+	"github.com/apache/servicecomb-mesher/proxy/config"
+	"github.com/go-chassis/go-archaius"
+)
+
+//error in ingress package
+var (
+	ErrNotMatch = errors.New("no matching rule")
+)
+var plugin = make(map[string]func() (RuleFetcher, error))
+
+//RuleFetcher query ingress rule
+type RuleFetcher interface {
+	Fetch(protocol, host, apiPath string, headers map[string][]string) (*config.IngressRule, error)
+}
+
+//DefaultFetcher fetch config
+var DefaultFetcher RuleFetcher
+
+//InstallPlugin install implementation
+func InstallPlugin(name string, f func() (RuleFetcher, error)) {
+	plugin[name] = f
+}
+
+//Init initialize
+func Init() error {
+	t := archaius.GetString("mesher.ingress.type", "servicecomb")
+	f, ok := plugin[t]
+	if !ok {
+		return fmt.Errorf("do not support [%s]", t)
+	}
+	var err error
+	DefaultFetcher, err = f()
+	return err
+}
diff --git a/proxy/ingress/servicecomb/ingress.go b/proxy/ingress/servicecomb/ingress.go
new file mode 100644
index 0000000..c251ca5
--- /dev/null
+++ b/proxy/ingress/servicecomb/ingress.go
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package servicecomb
+
+import (
+	"github.com/apache/servicecomb-mesher/proxy/config"
+	"github.com/apache/servicecomb-mesher/proxy/ingress"
+	"github.com/go-chassis/go-archaius"
+	"github.com/patrickmn/go-cache"
+	"regexp"
+	"time"
+)
+
+const (
+	cacheTTL       = 30
+	ingressRuleKey = "mesher.ingress.rule.http"
+)
+
+var rulesData []*config.IngressRule
+
+//IngressRuleFetcher query ingress rule
+type IngressRuleFetcher struct {
+	cache *cache.Cache
+}
+
+//Fetch get ingress rule
+func (f *IngressRuleFetcher) Fetch(protocol, host, apiPath string, headers map[string][]string) (*config.IngressRule, error) {
+	for _, r := range rulesData {
+		if r.Host != "" && host != r.Host {
+			//do not match host,then ignore path
+			continue
+		}
+		match, err := regexp.MatchString(r.APIPath, apiPath)
+		if err != nil {
+			return nil, err
+		}
+		if match {
+			return r, nil
+		}
+	}
+	return nil, ingress.ErrNotMatch
+}
+
+func newFetcher() (ingress.RuleFetcher, error) {
+	raw := archaius.GetString(ingressRuleKey, "")
+	rules, err := config.NewRules(raw)
+	if err != nil {
+		return nil, err
+	}
+
+	err = archaius.RegisterListener(&ingressRuleEventListener{}, ingressRuleKey)
+	if err != nil {
+		return nil, err
+	}
+	rulesData = rules.Value()
+	return &IngressRuleFetcher{
+		cache: cache.New(cacheTTL*time.Second, 0),
+	}, nil
+}
+
+func init() {
+	ingress.InstallPlugin("servicecomb", newFetcher)
+}
diff --git a/proxy/ingress/servicecomb/listener.go b/proxy/ingress/servicecomb/listener.go
new file mode 100644
index 0000000..a1cc7b8
--- /dev/null
+++ b/proxy/ingress/servicecomb/listener.go
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package servicecomb
+
+import (
+	"github.com/apache/servicecomb-mesher/proxy/config"
+	"github.com/go-chassis/go-archaius/core"
+	"github.com/go-chassis/go-chassis/core/common"
+	"github.com/go-mesh/openlogging"
+)
+
+type ingressRuleEventListener struct{}
+
+//Event update ingress rule
+func (r *ingressRuleEventListener) Event(e *core.Event) {
+	if e == nil {
+		openlogging.Warn("Event pointer is nil")
+		return
+	}
+	openlogging.Info("dark launch event", openlogging.WithTags(openlogging.Tags{
+		"key":   e.Key,
+		"event": e.EventType,
+		"rule":  e.Value,
+	}))
+	raw, ok := e.Value.(string)
+	if !ok {
+		openlogging.Error("invalid ingress rule", openlogging.WithTags(openlogging.Tags{
+			"value": raw,
+		}))
+	}
+	switch e.EventType {
+	case common.Update:
+		saveRules(raw)
+	case common.Create:
+		saveRules(raw)
+	case common.Delete:
+		rulesData = nil
+		openlogging.Info("ingress rule is removed", openlogging.WithTags(
+			openlogging.Tags{
+				"key": e.Key,
+			}))
+	}
+
+}
+
+func saveRules(raw string) {
+	rules, err := config.NewRules(raw)
+	if err != nil {
+		openlogging.Error("invalid ingress rule", openlogging.WithTags(openlogging.Tags{
+			"value": raw,
+		}))
+	}
+	rulesData = rules.Value()
+	openlogging.Info("update ingress rule", openlogging.WithTags(openlogging.Tags{
+		"value": raw,
+	}))
+}
diff --git a/proxy/pkg/egress/egress_test.go b/proxy/pkg/egress/egress_test.go
index e49d395..a1c9a03 100644
--- a/proxy/pkg/egress/egress_test.go
+++ b/proxy/pkg/egress/egress_test.go
@@ -19,7 +19,11 @@
 
 import (
 	"fmt"
+	"github.com/go-chassis/go-chassis/pkg/util/fileutil"
+	"github.com/stretchr/testify/assert"
+	"io"
 	"os"
+	"path/filepath"
 	"testing"
 
 	"github.com/apache/servicecomb-mesher/proxy/cmd"
@@ -36,9 +40,21 @@
 func BenchmarkMatch(b *testing.B) {
 	lager.Initialize("", "DEBUG", "",
 		"size", true, 1, 10, 7)
-
-	gopath := os.Getenv("GOPATH")
-	os.Setenv("CHASSIS_HOME", gopath+"/src/github.com/apache/servicecomb-mesher")
+	chassis := []byte(`
+cse:
+  service:
+    registry:
+      #disabled: false           optional:禁用注册发现选项,默认开始注册发现
+      type: servicecenter           #optional:可选zookeeper/servicecenter,zookeeper供中软使用,不配置的情况下默认为servicecenter
+      scope: full                   #optional:scope不为full时,只允许在本app间访问,不允许跨app访问;为full就是注册时允许跨app,并且发现本租户全部微服务
+      address: http://127.0.0.1:30100
+      #register: manual          optional:register不配置时默认为自动注册,可选参数有自动注册auto和手动注册manual
+  
+`)
+	d, _ := os.Getwd()
+	filename1 := filepath.Join(d, "chassis.yaml")
+	f1, err := os.OpenFile(filename1, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
+	_, err = f1.Write(chassis)
 	cmd.Init()
 	config.Init()
 	mesherconfig.Init()
@@ -68,7 +84,7 @@
           protocol: HTTP`
 
 	ss := mesherconfig.EgressConfig{}
-	err := yaml.Unmarshal([]byte(yamlContent), &ss)
+	err = yaml.Unmarshal([]byte(yamlContent), &ss)
 	if err != nil {
 		fmt.Println("unmarshal failed")
 	}
@@ -84,12 +100,44 @@
 	lager.Initialize("", "DEBUG", "",
 		"size", true, 1, 10, 7)
 
-	gopath := os.Getenv("GOPATH")
-	os.Setenv("CHASSIS_HOME", gopath+"/src/github.com/apache/servicecomb-mesher")
+	b := []byte(`
+cse:
+  service:
+    registry:
+      #disabled: false           optional:禁用注册发现选项,默认开始注册发现
+      type: servicecenter           #optional:可选zookeeper/servicecenter,zookeeper供中软使用,不配置的情况下默认为servicecenter
+      scope: full                   #optional:scope不为full时,只允许在本app间访问,不允许跨app访问;为full就是注册时允许跨app,并且发现本租户全部微服务
+      address: http://127.0.0.1:30100
+      #register: manual          optional:register不配置时默认为自动注册,可选参数有自动注册auto和手动注册manual
+  
+`)
+	d, _ := os.Getwd()
+	filename1 := filepath.Join(d, "chassis.yaml")
+	f1, err := os.OpenFile(filename1, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
+	assert.NoError(t, err)
+	_, err = f1.Write(b)
+	b = []byte(`
+---
+#微服务的私有属性
+#APPLICATION_ID: CSE #optional
+service_description:
+  name: Client
+  #version: 0.1 #optional
+
+`)
+	d, _ = os.Getwd()
+	filename1 = filepath.Join(d, "microservice.yaml")
+	os.Remove(filename1)
+	f1, err = os.Create(filename1)
+	assert.NoError(t, err)
+	defer f1.Close()
+	_, err = io.WriteString(f1, string(b))
+	assert.NoError(t, err)
+	os.Setenv(fileutil.ChassisConfDir, d)
 	cmd.Init()
-	config.Init()
-	mesherconfig.Init()
-	egress.Init()
+	err = config.Init()
+	err = mesherconfig.Init()
+	err = egress.Init()
 	//control.Init()
 	var yamlContent = `---
 egress:
@@ -111,20 +159,20 @@
           protocol: HTTP`
 
 	ss := mesherconfig.EgressConfig{}
-	err := yaml.Unmarshal([]byte(yamlContent), &ss)
+	err = yaml.Unmarshal([]byte(yamlContent), &ss)
 	if err != nil {
 		fmt.Println("unmarshal failed")
 	}
 	archaius.SetEgressRule(ss.Destinations)
 
 	myString := "www.google.com"
-	b, _ := egress.Match(myString)
-	if b == false {
+	c, _ := egress.Match(myString)
+	if c == false {
 		t.Errorf("Expected true but got false")
 	}
 	myString = "*.yahoo.com"
-	b, _ = egress.Match(myString)
-	if b == false {
+	c, _ = egress.Match(myString)
+	if c == false {
 		t.Errorf("Expected true but got false")
 	}
 }
diff --git a/proxy/pkg/runtime/runtime.go b/proxy/pkg/runtime/runtime.go
index 56a14bc..8a511df 100644
--- a/proxy/pkg/runtime/runtime.go
+++ b/proxy/pkg/runtime/runtime.go
@@ -18,6 +18,6 @@
 package runtime
 
 var (
-	//Mode is of type string which gives mode of mesher deployment
-	Mode string
+	//Role is of type string which gives mode of mesher deployment
+	Role string
 )
diff --git a/proxy/protocol/dubbo/proxy/dubbo_proxy_ouput.go b/proxy/protocol/dubbo/proxy/dubbo_proxy_ouput.go
index 687b32d..571b19e 100755
--- a/proxy/protocol/dubbo/proxy/dubbo_proxy_ouput.go
+++ b/proxy/protocol/dubbo/proxy/dubbo_proxy_ouput.go
@@ -226,7 +226,7 @@
 			ctx.Req.SetAttachment(common.HeaderSourceName, chassisconfig.SelfServiceName)
 			ctx.Req.SetAttachment(ProxyTag, "true")
 
-			if mesherRuntime.Mode == mesherCommon.ModeSidecar {
+			if mesherRuntime.Role == mesherCommon.RoleSidecar {
 				c, err = handler.GetChain(common.Consumer, mesherCommon.ChainConsumerOutgoing)
 				if err != nil {
 					openlogging.Error("Get Consumer chain failed: " + err.Error())
@@ -330,12 +330,12 @@
 		h[k] = req.Header.Get(k)
 	}
 	//Resolve Destination
-	_, err = dr.Resolve(source, h, inv.URLPathFormat, &inv.MicroServiceName)
+	destination, _, err := dr.Resolve(source, "", inv.URLPathFormat, h)
 	if err != nil {
 		return err
 	}
-
-	if mesherRuntime.Mode == mesherCommon.ModeSidecar {
+	inv.MicroServiceName = destination
+	if mesherRuntime.Role == mesherCommon.RoleSidecar {
 		c, err = handler.GetChain(common.Consumer, mesherCommon.ChainConsumerOutgoing)
 		if err != nil {
 			lager.Logger.Error("Get chain failed: " + err.Error())
diff --git a/proxy/protocol/grpc/reverse_proxy.go b/proxy/protocol/grpc/reverse_proxy.go
index 6da6843..3cc62a2 100755
--- a/proxy/protocol/grpc/reverse_proxy.go
+++ b/proxy/protocol/grpc/reverse_proxy.go
@@ -106,12 +106,12 @@
 	if r.URL.Host == "" {
 		r.URL.Host = r.Host
 	}
-	port, err := dr.Resolve(source, h, r.URL.String(), &inv.MicroServiceName)
+	serviceName, port, err := dr.Resolve(source, "", r.URL.String(), h)
 	if err != nil {
 		WriteErrorResponse(inv, w, r, http.StatusBadRequest, err)
 		return
 	}
-
+	inv.MicroServiceName = serviceName
 	if port != "" {
 		h[XForwardedPort] = port
 	}
diff --git a/proxy/protocol/grpc/server.go b/proxy/protocol/grpc/server.go
index c51f191..435a477 100644
--- a/proxy/protocol/grpc/server.go
+++ b/proxy/protocol/grpc/server.go
@@ -72,10 +72,10 @@
 		return fmt.Errorf("only support ipv4, input is [%s]", hs.opts.Address)
 	}
 
-	switch runtime.Mode {
-	case common.ModeSidecar:
+	switch runtime.Role {
+	case common.RoleSidecar:
 		err = hs.startSidecar(host, port)
-	case common.ModePerHost:
+	default:
 		err = hs.startPerHost()
 	}
 
diff --git a/proxy/protocol/http/gateway.go b/proxy/protocol/http/gateway.go
new file mode 100644
index 0000000..ff8f173
--- /dev/null
+++ b/proxy/protocol/http/gateway.go
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package http
+
+import (
+	"github.com/apache/servicecomb-mesher/proxy/common"
+	"github.com/apache/servicecomb-mesher/proxy/ingress"
+	"github.com/go-chassis/go-chassis/client/rest"
+	chassiscommon "github.com/go-chassis/go-chassis/core/common"
+	"github.com/go-chassis/go-chassis/core/handler"
+	"github.com/go-chassis/go-chassis/core/invocation"
+	"github.com/go-mesh/openlogging"
+	"net/http"
+)
+
+func handleIncomingTraffic(inv *invocation.Invocation) (*invocation.Response, error) {
+	c, err := handler.GetChain(chassiscommon.Provider, common.ChainProviderIncoming)
+	if err != nil {
+		openlogging.Error("Get chain failed: " + err.Error())
+		return nil, err
+	}
+	var invRsp *invocation.Response
+	c.Next(inv, func(ir *invocation.Response) error {
+		invRsp = ir
+		if invRsp != nil {
+			return invRsp.Err
+		}
+		return nil
+	})
+	return invRsp, nil
+}
+
+//HandleIngressTraffic is api gateway http handler
+func HandleIngressTraffic(w http.ResponseWriter, r *http.Request) {
+	inv := &invocation.Invocation{}
+	inv.Reply = rest.NewResponse()
+	inv.Protocol = "rest"
+	h := make(map[string]string)
+	for k := range r.Header {
+		h[k] = r.Header.Get(k)
+	}
+	inv.Ctx = chassiscommon.NewContext(h)
+	invResp, err := handleIncomingTraffic(inv)
+	if err != nil {
+		handleErrorResponse(inv, w, http.StatusInternalServerError, err)
+		return
+	}
+	if invResp != nil {
+		if invResp.Status != 0 || invResp.Err != nil {
+			handleErrorResponse(inv, w, invResp.Status, invResp.Err)
+			return
+		}
+	}
+	rule, err := ingress.DefaultFetcher.Fetch("http", r.Host, r.URL.Path, r.Header)
+	if err != nil {
+		handleErrorResponse(inv, w, http.StatusInternalServerError, err)
+		return
+	}
+	inv.MicroServiceName = rule.Service.Name
+	targetAPI := r.URL.Path
+	if rule.Service.RedirectPath != "" {
+		targetAPI = rule.Service.RedirectPath
+	}
+	newReq, err := http.NewRequest(r.Method, "http://"+inv.MicroServiceName+targetAPI, r.Body)
+	if err != nil {
+		handleErrorResponse(inv, w, http.StatusInternalServerError, err)
+		return
+	}
+	inv.Args = newReq
+	h[XForwardedPort] = rule.Service.Port.Value
+	c, err := handler.GetChain(chassiscommon.Consumer, common.ChainConsumerOutgoing)
+	if err != nil {
+		handleErrorResponse(inv, w, http.StatusBadGateway, err)
+		openlogging.Error("Get chain failed: " + err.Error())
+		return
+	}
+	var invRsp *invocation.Response
+	c.Next(inv, func(ir *invocation.Response) error {
+		//Send the request to the destination
+		invRsp = ir
+		if invRsp != nil {
+			return invRsp.Err
+		}
+		return nil
+	})
+	resp, err := handleRequest(w, inv, invRsp)
+	if err != nil {
+		openlogging.Error("Handle request failed: " + err.Error())
+		return
+	}
+	RecordStatus(inv, resp.StatusCode)
+}
diff --git a/proxy/protocol/http/http_server.go b/proxy/protocol/http/http_server.go
index b47dc3a..c7b73e6 100644
--- a/proxy/protocol/http/http_server.go
+++ b/proxy/protocol/http/http_server.go
@@ -18,24 +18,26 @@
 package http
 
 import (
+	"context"
 	"crypto/tls"
 	"errors"
 	"fmt"
-	"github.com/apache/servicecomb-mesher/proxy/common"
-	"github.com/apache/servicecomb-mesher/proxy/config"
-	"github.com/apache/servicecomb-mesher/proxy/protocol/dubbo/proxy"
-	"github.com/apache/servicecomb-mesher/proxy/resolver"
+	"github.com/apache/servicecomb-mesher/proxy/ingress"
 	"net"
 	"net/http"
 	"strings"
 
-	"context"
+	"github.com/apache/servicecomb-mesher/proxy/common"
+	"github.com/apache/servicecomb-mesher/proxy/config"
 	"github.com/apache/servicecomb-mesher/proxy/pkg/runtime"
+	"github.com/apache/servicecomb-mesher/proxy/protocol/dubbo/proxy"
+	"github.com/apache/servicecomb-mesher/proxy/resolver"
 	chassisCom "github.com/go-chassis/go-chassis/core/common"
 	chassisConfig "github.com/go-chassis/go-chassis/core/config"
 	"github.com/go-chassis/go-chassis/core/lager"
 	"github.com/go-chassis/go-chassis/core/server"
 	chassisTLS "github.com/go-chassis/go-chassis/core/tls"
+	chassisRuntime "github.com/go-chassis/go-chassis/pkg/runtime"
 	"github.com/go-mesh/openlogging"
 )
 
@@ -75,11 +77,11 @@
 		return fmt.Errorf("only support ipv4, input is [%s]", hs.opts.Address)
 	}
 
-	switch runtime.Mode {
-	case common.ModeSidecar:
+	switch runtime.Role {
+	case common.RoleSidecar:
 		err = hs.startSidecar(host, port)
-	case common.ModePerHost:
-		err = hs.startPerHost()
+	default:
+		err = hs.startCommonProxy()
 	}
 	if err != nil {
 		return err
@@ -139,20 +141,22 @@
 	return nil
 }
 
-func (hs *httpServer) startPerHost() error {
-	sslTag := genTag(common.ComponentName, chassisCom.Provider)
+func (hs *httpServer) startCommonProxy() error {
+	if err := ingress.Init(); err != nil {
+		return err
+	}
 	mesherTLSConfig, mesherSSLConfig, err := chassisTLS.GetTLSConfigByService(
-		common.ComponentName, "", chassisCom.Provider)
+		chassisRuntime.ServiceName, "rest", chassisCom.Provider)
 	if err != nil {
 		if !chassisTLS.IsSSLConfigNotExist(err) {
 			return err
 		}
 	} else {
-		lager.Logger.Warnf("%s TLS mode, verify peer: %t, cipher plugin: %s.",
-			sslTag, mesherSSLConfig.VerifyPeer, mesherSSLConfig.CipherPlugin)
+		lager.Logger.Warnf("TLS mode, verify peer: %t, cipher plugin: %s.",
+			mesherSSLConfig.VerifyPeer, mesherSSLConfig.CipherPlugin)
 	}
 
-	err = hs.listenAndServe(hs.opts.Address, mesherTLSConfig, http.HandlerFunc(LocalRequestHandler))
+	err = hs.listenAndServe(hs.opts.Address, mesherTLSConfig, http.HandlerFunc(HandleIngressTraffic))
 	if err != nil {
 		return err
 	}
@@ -165,6 +169,7 @@
 		return err
 	}
 	if t != nil {
+		openlogging.Info("run as https")
 		lnTLS := tls.NewListener(ln, t)
 		ln = lnTLS
 	}
@@ -181,7 +186,7 @@
 }
 
 func (hs *httpServer) Stop() error {
-	//go 1.8+ drain connections before stop server
+	//go 1.8+ drain connections handleIncomingTraffic stop server
 	if hs.server == nil {
 		openlogging.Info("http server don't need to be stopped")
 		return nil
diff --git a/proxy/protocol/http/reverse_proxy.go b/proxy/protocol/http/sidecar.go
similarity index 98%
rename from proxy/protocol/http/reverse_proxy.go
rename to proxy/protocol/http/sidecar.go
index 09d6357..144e852 100755
--- a/proxy/protocol/http/reverse_proxy.go
+++ b/proxy/protocol/http/sidecar.go
@@ -95,7 +95,7 @@
 func LocalRequestHandler(w http.ResponseWriter, r *http.Request) {
 	prepareRequest(r)
 	inv := consumerPreHandler(r)
-	source := stringutil.SplitFirstSep(r.RemoteAddr, ":")
+	remoteIP := stringutil.SplitFirstSep(r.RemoteAddr, ":")
 
 	var err error
 	h := make(map[string]string)
@@ -103,12 +103,12 @@
 		h[k] = r.Header.Get(k)
 	}
 	//Resolve Destination
-	port, err := dr.Resolve(source, h, r.URL.String(), &inv.MicroServiceName)
+	destination, port, err := dr.Resolve(remoteIP, r.Host, r.URL.String(), h)
 	if err != nil {
 		handleErrorResponse(inv, w, http.StatusBadRequest, err)
 		return
 	}
-
+	inv.MicroServiceName = destination
 	if port != "" {
 		h[XForwardedPort] = port
 	}
diff --git a/proxy/resolver/authority/destination.go b/proxy/resolver/authority/destination.go
index b6e2467..577a503 100644
--- a/proxy/resolver/authority/destination.go
+++ b/proxy/resolver/authority/destination.go
@@ -29,16 +29,15 @@
 }
 
 //Resolve resolves service name
-func (dr *GRPCDefaultDestinationResolver) Resolve(sourceAddr string, header map[string]string, rawURI string, destinationName *string) (string, error) {
+func (dr *GRPCDefaultDestinationResolver) Resolve(sourceAddr, host, rawURI string, header map[string]string) (string, string, error) {
 	s := strings.Split(rawURI, ":")
 	if len(s) != 2 {
 		err := fmt.Errorf("can not parse [%s]", rawURI)
 		openlogging.Error(err.Error())
-		return "", err
+		return "", "", err
 	}
 
-	*destinationName = s[0]
-	return s[1], nil
+	return s[0], s[1], nil
 }
 
 //New return return dr
diff --git a/proxy/resolver/authority/destination_test.go b/proxy/resolver/authority/destination_test.go
index a2a5967..ecc0391 100644
--- a/proxy/resolver/authority/destination_test.go
+++ b/proxy/resolver/authority/destination_test.go
@@ -34,35 +34,32 @@
 	header := http.Header{}
 	header.Add("cookie", "user=jason")
 	header.Add("X-Age", "18")
-	mystring := "Server"
-	var destinationString = &mystring
-	p, err := d.Resolve("abc", map[string]string{}, "127.0.1.1", destinationString)
+	var destinationString = "Server"
+	destinationString, p, err := d.Resolve("abc", "", "127.0.1.1", map[string]string{})
 	assert.Error(t, err)
 	assert.Equal(t, "", p)
 
-	p, err = d.Resolve("abc", map[string]string{}, "", destinationString)
+	destinationString, p, err = d.Resolve("abc", "", "", map[string]string{})
 	assert.Error(t, err)
 	assert.Equal(t, "", p)
 
-	p, err = d.Resolve("abc", map[string]string{}, "127.0.0.1:80", destinationString)
+	destinationString, p, err = d.Resolve("abc", "", "127.0.0.1:80", map[string]string{})
 	assert.NoError(t, err)
 	assert.Equal(t, "80", p)
 
 	dr := resolver.GetDestinationResolver("grpc")
 
-	p, err = dr.Resolve("abc", map[string]string{}, "127.0.0.1:80", destinationString)
+	destinationString, p, err = dr.Resolve("abc", "", "127.0.0.1:80", map[string]string{})
 	assert.NoError(t, err)
 	assert.Equal(t, "80", p)
-
+	t.Log(destinationString)
 }
 
 func BenchmarkDefaultDestinationResolver_Resolve(b *testing.B) {
 	lager.Initialize("", "DEBUG", "",
 		"size", true, 1, 10, 7)
 	d := &authority.GRPCDefaultDestinationResolver{}
-	mystring := "Server"
-	var destinationString = &mystring
 	for i := 0; i < b.N; i++ {
-		d.Resolve("abc", map[string]string{}, "127.0.0.1:80", destinationString)
+		d.Resolve("abc", "", "127.0.0.1:80", map[string]string{})
 	}
 }
diff --git a/proxy/resolver/destination.go b/proxy/resolver/destination.go
index 0d62faf..1432186 100644
--- a/proxy/resolver/destination.go
+++ b/proxy/resolver/destination.go
@@ -43,34 +43,34 @@
 
 //DestinationResolver is a interface with Resolve method
 type DestinationResolver interface {
-	Resolve(sourceAddr string, header map[string]string, rawURI string, destinationName *string) (string, error)
+	Resolve(remoteIP, host, rawURI string, header map[string]string) (string, string, error)
 }
 
 //DefaultDestinationResolver is a struct
+//mesher as sidecar must use DefaultDestinationResolver
 type DefaultDestinationResolver struct {
 }
 
 //Resolve resolves service's endpoint
 //service may have multiple port for same protocol
-func (dr *DefaultDestinationResolver) Resolve(sourceAddr string, header map[string]string, rawURI string, destinationName *string) (string, error) {
+func (dr *DefaultDestinationResolver) Resolve(remoteIP, host, rawURI string, header map[string]string) (string, string, error) {
 	u, err := url.Parse(rawURI)
 	if err != nil {
 		openlogging.Error("Can not parse url: " + err.Error())
-		return "", err
+		return "", "", err
 	}
 
 	if u.Host == "" {
-		return "", errors.New(`Invalid uri, please check:
+		return "", "", errors.New(`Invalid uri, please check:
 1, For provider, mesher listens on external ip
 2, Set http_proxy as mesher address, before sending request`)
 	}
 
 	if u.Host == SelfEndpoint {
-		return "", errors.New(`uri format must be: http://serviceName/api`)
+		return "", "", errors.New(`uri format must be: http://serviceName/api`)
 	}
 
-	*destinationName = u.Hostname()
-	return u.Port(), nil
+	return u.Hostname(), u.Port(), nil
 }
 
 //New function returns new DefaultDestinationResolver struct object
diff --git a/proxy/resolver/destination_test.go b/proxy/resolver/destination_test.go
index b95a0e0..ae647d7 100644
--- a/proxy/resolver/destination_test.go
+++ b/proxy/resolver/destination_test.go
@@ -61,26 +61,26 @@
 	header := http.Header{}
 	header.Add("cookie", "user=jason")
 	header.Add("X-Age", "18")
-	mystring := "Server"
-	var destinationString = &mystring
-	p, err := d.Resolve("abc", map[string]string{}, "127.0.1.1", destinationString)
+	destinationString := "Server"
+	destinationString, p, err := d.Resolve("127.0.1.1", "abc", "", map[string]string{})
 	assert.Error(t, err)
 	assert.Equal(t, "", p)
 
-	p, err = d.Resolve("abc", map[string]string{}, "", destinationString)
+	destinationString, p, err = d.Resolve("abc", "", "", map[string]string{})
 	assert.Error(t, err)
 	assert.Equal(t, "", p)
 
-	p, err = d.Resolve("abc", map[string]string{}, "http://127.0.0.1:80/test", destinationString)
+	destinationString, p, err = d.Resolve("abc", "", "http://127.0.0.1:80/test", map[string]string{})
 	assert.NoError(t, err)
 	assert.Equal(t, "80", p)
 
-	p, err = d.Resolve("abc", map[string]string{}, "Server:80/test", destinationString)
+	destinationString, p, err = d.Resolve("abc", "", "Server:80/test", map[string]string{})
 	assert.Error(t, err)
 
-	p, err = d.Resolve("abc", map[string]string{}, "127.0.0.1:80", destinationString)
+	destinationString, p, err = d.Resolve("abc", "", "127.0.0.1:80", map[string]string{})
 	assert.Error(t, err)
 	assert.Equal(t, "", p)
+	t.Log(destinationString)
 }
 
 func TestGetDestinationResolver(t *testing.T) {
@@ -97,9 +97,7 @@
 	lager.Initialize("", "DEBUG", "",
 		"size", true, 1, 10, 7)
 	d := &DefaultDestinationResolver{}
-	mystring := "Server"
-	var destinationString = &mystring
 	for i := 0; i < b.N; i++ {
-		d.Resolve("abc", map[string]string{}, "http://127.0.0.1:80/test", destinationString)
+		d.Resolve("abc", "", "http://127.0.0.1:80/test", map[string]string{})
 	}
 }
diff --git a/proxy/util/compara_test.go b/proxy/util/compara_test.go
deleted file mode 100644
index ebaf1a9..0000000
--- a/proxy/util/compara_test.go
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package util_test
-
-import (
-	"github.com/apache/servicecomb-mesher/proxy/config"
-	"github.com/apache/servicecomb-mesher/proxy/util"
-	"github.com/go-chassis/go-chassis/core/invocation"
-	"github.com/go-chassis/go-chassis/pkg/util/tags"
-	"github.com/stretchr/testify/assert"
-	"testing"
-)
-
-func TestEqualPolicy(t *testing.T) {
-
-	i := &invocation.Invocation{
-		MicroServiceName: "ShoppingCart",
-	}
-
-	i.RouteTags = utiltags.NewDefaultTag("0.1", "default")
-	tags := make(map[string]string)
-	tags["app"] = "default"
-	tags["version"] = "0.0.1"
-	p := &config.Policy{
-		Destination:   "ShoppingCart1",
-		Tags:          tags,
-		LoadBalancing: nil,
-	}
-	value := util.EqualPolicy(i, p)
-	assert.Equal(t, value, false)
-
-	i = &invocation.Invocation{
-		MicroServiceName: "ShoppingCart",
-	}
-
-	i.RouteTags = utiltags.NewDefaultTag("0.1", "default1")
-	tags = make(map[string]string)
-	tags["app"] = "default"
-	tags["version"] = "0.0.1"
-	p = &config.Policy{
-		Destination:   "ShoppingCart",
-		Tags:          tags,
-		LoadBalancing: nil,
-	}
-	value = util.EqualPolicy(i, p)
-	assert.Equal(t, value, false)
-	i = &invocation.Invocation{
-		MicroServiceName: "ShoppingCart",
-	}
-
-	i.RouteTags = utiltags.NewDefaultTag("0.1", "default")
-	tags = make(map[string]string)
-	tags["app"] = "default"
-
-	tags["version"] = "0.0.1"
-	p = &config.Policy{
-		Destination:   "ShoppingCart",
-		Tags:          tags,
-		LoadBalancing: nil,
-	}
-	value = util.EqualPolicy(i, p)
-	assert.Equal(t, value, false)
-
-	i = &invocation.Invocation{
-		MicroServiceName: "ShoppingCart",
-	}
-
-	i.RouteTags = utiltags.NewDefaultTag("0.1", "default")
-	tags = make(map[string]string)
-	tags["app1"] = "default"
-	tags["version1"] = "0.1"
-	p = &config.Policy{
-		Destination:   "ShoppingCart",
-		Tags:          tags,
-		LoadBalancing: nil,
-	}
-	value = util.EqualPolicy(i, p)
-	assert.Equal(t, value, false)
-
-	i = &invocation.Invocation{
-		MicroServiceName: "ShoppingCart",
-	}
-	inv := make(map[string]interface{})
-	inv["app1"] = 1
-	i.Metadata = inv
-	i.RouteTags = utiltags.NewDefaultTag("0.1", "default")
-	tags = make(map[string]string)
-	tags["app1"] = "default"
-	tags["version1"] = "0.1"
-	p = &config.Policy{
-		Destination:   "ShoppingCart",
-		Tags:          tags,
-		LoadBalancing: nil,
-	}
-	value = util.EqualPolicy(i, p)
-	assert.Equal(t, value, false)
-
-	i = &invocation.Invocation{
-		MicroServiceName: "ShoppingCart",
-	}
-	inv = make(map[string]interface{})
-	inv["app"] = "default"
-	i.Metadata = inv
-	i.RouteTags = utiltags.NewDefaultTag("0.1", "default")
-	tags = make(map[string]string)
-	tags["app"] = "default1"
-	tags["version"] = "0.1"
-	p = &config.Policy{
-		Destination:   "ShoppingCart",
-		Tags:          tags,
-		LoadBalancing: nil,
-	}
-	value = util.EqualPolicy(i, p)
-	assert.Equal(t, value, false)
-
-	i = &invocation.Invocation{
-		MicroServiceName: "ShoppingCart",
-	}
-
-	i.RouteTags = utiltags.NewDefaultTag("0.1", "default")
-	tags = make(map[string]string)
-	tags["app"] = "default"
-	tags["version"] = "0.1"
-	p = &config.Policy{
-		Destination:   "ShoppingCart",
-		Tags:          tags,
-		LoadBalancing: nil,
-	}
-	value = util.EqualPolicy(i, p)
-	assert.Equal(t, value, true)
-
-}
diff --git a/proxy/util/compare.go b/proxy/util/compare.go
deleted file mode 100644
index 7b72659..0000000
--- a/proxy/util/compare.go
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package util
-
-import (
-	"github.com/apache/servicecomb-mesher/proxy/common"
-	"github.com/apache/servicecomb-mesher/proxy/config"
-	"github.com/go-chassis/go-chassis/core/invocation"
-)
-
-//EqualPolicy is a function
-func EqualPolicy(inv *invocation.Invocation, p *config.Policy) bool {
-	if inv.MicroServiceName != p.Destination {
-		return false
-	}
-	for k, v := range p.Tags {
-		if k == common.BuildInTagApp {
-			if v == "" {
-				v = common.DefaultApp
-			}
-			if v != inv.RouteTags.AppID() {
-				return false
-			}
-			continue
-		}
-		if k == common.BuildInTagVersion {
-			if v == "" {
-				v = common.DefaultVersion
-			}
-			if v != inv.RouteTags.Version() {
-				return false
-			}
-			continue
-		}
-		t, ok := inv.Metadata[k]
-		if !ok {
-			return false
-		}
-		if _, ok := t.(string); !ok {
-			return false
-		}
-	}
-	for k, v := range inv.Metadata {
-		if v != p.Tags[k] {
-			return false
-		}
-	}
-	return true
-
-}