Exemple #1
0
func main() {
	services := []struct {
		uri string
		svc host.Service
	}{
		// Examples
		{
			"/core/examples",
			host.NewFactoryServiceContext(&host.ExampleFactoryService{}),
		},
		// Examples
		{
			"/core/ping",
			host.NewPingService(),
		},
	}

	var err error

	flag.Parse()

	glog.Infof("Started with %s", os.Args[1:])

	h := host.NewServiceHost()
	err = h.Initialize(bindAddress.String())
	if err != nil {
		glog.Fatalf("Error initializing: %s\n", err)
	}

	ctx := operation.SetAuthorizationToken(context.Background(), authToken)
	_, err = host.GetServiceHostManagementState(ctx)
	if err != nil {
		glog.Fatalf("Error getting ServiceHostState: %s\n", err)
	}

	var ops []*operation.Operation
	for _, s := range services {
		op := operation.NewPost(ctx, uri.Extend(uri.Empty(), s.uri), nil)
		ops = append(ops, op)
		h.StartService(op, s.svc)
	}

	_, err = operation.Join(ops)
	if err != nil {
		glog.Fatalf("Error starting services: %s", err)
	}

	start(h)
}
Exemple #2
0
// ServeHTTP implements the host's core http entry point.
func (h *ServiceHost) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	ctx := context.Background()
	op := operation.NewOperation(ctx)
	op.SetRequest(req)

	if glog.V(xenon.Debug) {
		glog.Infof("host: %s %s", req.Method, req.URL.Path)
	}

	// Create context for handling this request. The request associated with
	// this operation might complete long before the workflow that it kicked
	// off completes. This workflow needs to flow parameters such as those
	// related to authorization to other operations and workflows.
	// On the Java side this is solved by using thread locals that are carefully
	// set when an operation is handled, making sure they can automatically be
	// flowed to newly created operations. On the Go side there is no equivalent
	// for thread locals so this context has to be passed around explicitly.
	if t := req.Header.Get(operation.RequestAuthTokenHeader); t != "" {
		ctx = operation.SetAuthorizationToken(ctx, t)
	}

	// Operations may be marked complete before this function returns.
	// Handle the request in a separate routine to return to the client ASAP.
	op.Start()

	go h.HandleRequest(ctx, op)

	if err := op.Wait(); err != nil {
		if handler, ok := err.(http.Handler); ok {
			if glog.V(xenon.Debug) {
				glog.Warningf("host: %s %s: custom error handler", req.Method, req.URL.Path)
			}

			handler.ServeHTTP(rw, req)
			return
		}

		body := &common.ServiceErrorResponse{
			Message: err.Error(),
		}

		op.SetStatusCode(http.StatusInternalServerError)
		op.SetBody(body)
	}

	// Default status code to 200 OK
	code := op.GetStatusCode()
	if code == 0 {
		code = http.StatusOK
	}

	if glog.V(xenon.Debug) {
		glog.Infof("host: %s %s: status %d", req.Method, req.URL.Path, code)
	}

	if !op.IsStreamResponse() {
		rw.Header().Set(operation.ContentType, operation.ApplicationJSON)
	}

	rw.WriteHeader(code)
	if err := op.EncodeBody(rw); err != nil && err != operation.ErrBodyNotSet {
		glog.Warningf("host: failure writing body: %s\n", err)
	}
}