Giter Club home page Giter Club logo

go-endpoints's Introduction

Notice

This package provides Go support for Cloud Endpoints Frameworks v1, which is DEPRECATED and will be shut down on August 2, 2018.

This package is unmaintained and comes with no support or guarantee.

If used this product and were primarily interested in code generation and API specifications, you should probably investigate the OpenAPI specification and ecosystem.

If you want API authentication and monitoring, you should check out the newer Google Cloud Endpoints product (using OpenAPI or gRPC). Unfortunately, App Engine standard is not supported, so you will need to move your API to App Engine flexible, Compute Engine, or Kubernetes.












Cloud Endpoints for Go

This package will let you write Cloud Endpoints backends in Go.

If you're not familiar with Cloud Endpoints, see Google App Engine official documentation for Python or Java.

Install

Use goapp tool from the Google App Engine SDK for Go to get the package:

GO_APPENGINE/goapp get github.com/GoogleCloudPlatform/go-endpoints/endpoints

If you'll ever need to pull updates from the upstream, execute git pull from the root of this repo.

Alternatively, if you don't have goapp for some reason, do the standard

go get github.com/GoogleCloudPlatform/go-endpoints/endpoints

If this is not the first time you're "getting" the package, add -u param to get an updated version, i.e. go get -u ....

Now, you'll see a couple errors:

package appengine: unrecognized import path "appengine"
package appengine/user: unrecognized import path "appengine/user"
package appengine_internal/user: unrecognized import path "appengine_internal/user"

which is OK, don't worry! The issue here is Go looks at all imports in endpoints package and cannot find "appengine/*" packages nowhere in your $GOPATH. That's because they're not there, indeed. Appengine packages are normally available only when running an app with dev appserver, and since that's precisely what we want to do, "unrecognized import path" errors can be safely ignored.

Usage

Declare structs which describe your data. For instance:

// Greeting is a datastore entity that represents a single greeting.
// It also serves as (a part of) a response of GreetingService.
type Greeting struct {
  Key     *datastore.Key `json:"id" datastore:"-"`
  Author  string         `json:"author"`
  Content string         `json:"content" datastore:",noindex" endpoints:"req"`
  Date    time.Time      `json:"date"`
}

// GreetingsList is a response type of GreetingService.List method
type GreetingsList struct {
  Items []*Greeting `json:"items"`
}

// Request type for GreetingService.List
type GreetingsListReq struct {
  Limit int `json:"limit" endpoints:"d=10"`
}

Then, a service:

// GreetingService can sign the guesbook, list all greetings and delete
// a greeting from the guestbook.
type GreetingService struct {
}

// List responds with a list of all greetings ordered by Date field.
// Most recent greets come first.
func (gs *GreetingService) List(c context.Context, r *GreetingsListReq) (*GreetingsList, error) {
  if r.Limit <= 0 {
    r.Limit = 10
  }

  q := datastore.NewQuery("Greeting").Order("-Date").Limit(r.Limit)
  greets := make([]*Greeting, 0, r.Limit)
  keys, err := q.GetAll(c, &greets)
  if err != nil {
    return nil, err
  }

  for i, k := range keys {
    greets[i].Key = k
  }
  return &GreetingsList{greets}, nil
}

We can also define methods that don't require a response or a request.

// Add adds a greeting.
func (gs *GreetingService) Add(c context.Context, g *Greeting) error {
    k := datastore.NewIncompleteKey(c, "Greeting", nil)
    _, err := datastore.Put(c, k, g)
    return err
}

type Count struct {
    N int `json:"count"`
}

// Count returns the number of greetings.
func (gs *GreetingService) Count(c context.Context) (*Count, error) {
    n, err := datastore.NewQuery("Greeting").Count(c)
    if err != nil {
        return nil, err
    }
    return &Count{n}, nil
}

Last step is to make the above available as a discoverable API and leverage all the juicy stuff Cloud Endpoints are great at.

import "github.com/GoogleCloudPlatform/go-endpoints/endpoints"

func init() {
  greetService := &GreetingService{}
  api, err := endpoints.RegisterService(greetService,
    "greeting", "v1", "Greetings API", true)
  if err != nil {
    log.Fatalf("Register service: %v", err)
  }

  register := func(orig, name, method, path, desc string) {
      m := api.MethodByName(orig)
      if m == nil {
          log.Fatalf("Missing method %s", orig)
      }
      i := m.Info()
      i.Name, i.HTTPMethod, i.Path, i.Desc = name, method, path, desc
  }

  register("List", "greets.list", "GET", "greetings", "List most recent greetings.")
  register("Add", "greets.add", "PUT", "greetings", "Add a greeting.")
  register("Count", "greets.count", "GET", "greetings/count", "Count all greetings.")
  endpoints.HandleHTTP()
}

Don't forget to add URL matching in app.yaml:

application: my-app-id
version: v1
threadsafe: true

runtime: go
api_version: go1

handlers:
- url: /.*
  script: _go_app

# Important! Even though there's a catch all routing above,
# without these two lines it's not going to work.
# Make sure you have this:
- url: /_ah/spi/.*
  script: _go_app

That's it. It is time to start dev server and enjoy the discovery doc at localhost:8080/_ah/api/discovery/v1/apis/greeting/v1/rest

Naturally, API Explorer works too: localhost:8080/_ah/api/explorer

Time to deploy the app on appengine.appspot.com!

N.B. At present, you can't map your endpoint URL to a custom domain. Bossylobster wrote: "It's a non-trivial networking problem and something Google certainly plan on supporting in the future. Keep in mind, Cloud Endpoints is a combination or App Engine and Google's API Infrastructure."

Generate client libs

Now that we have the discovery doc, let's generate some client libraries.

Android

$ URL='https://my-app-id.appspot.com/_ah/api/discovery/v1/apis/greeting/v1/rest'
$ curl -s $URL > greetings.rest.discovery

# Optionally check the discovery doc
$ less greetings.rest.discovery

$ GO_SDK/endpointscfg.py gen_client_lib java greetings.rest.discovery

You should be able to find ./greetings.rest.zip file with Java client source code and its dependencies.

Once you have that, follow the official guide: Using Endpoints in an Android Client.

iOS

# Note the rpc suffix in the URL:
$ URL='https://my-app-id.appspot.com/_ah/api/discovery/v1/apis/greeting/v1/rpc'
$ curl -s $URL > greetings.rpc.discovery

# Optionally check the discovery doc
$ less greetings.rpc.discovery

Then, feed greetings.rpc.discovery file to the library generator on OS X as described in the official guide Using Endpoints in an iOS Client.

### JavaScript

There's really nothing to generate for JavaScript, you just use it!

Here's the official guide: Using Endpoints in a JavaScript client.

Dart

# Clone or fork discovery_api_dart_client_generator
git clone https://github.com/dart-gde/discovery_api_dart_client_generator
cd discovery_api_dart_client_generator
pub install

# Generate your client library:
mkdir input
URL='https://my-app-id.appspot.com/_ah/api/discovery/v1/apis/greeting/v1/rest'
curl -s -o input/greeting.json $URL
bin/generate.dart package -i input -o ../dart_my-app-id_v1_api_client --package-name my-app-id_v1_api

Now you just have to add your endpoints client library to your dart application (assuming it is in the parent directory.)

cd ../my-app_dart/
cat >>pubspec.yaml <<EOF
  my-app-id_v1_api:
  path: ../dart_my-app-id_v1_api_client
EOF

Take a look at the api client examples to get a feel on how to use your library.

Docs

Samples

Check out the famous TicTacToe app. It has its own readme file.

Or you can just play it on the live demo app.

Running tests

You'll need Google App Engine SDK for Go to run tests.

Once you get that installed, use goapp tool to run all tests from the root of this repo:

GO_APPENGINE_SDK/goapp test ./endpoints

The tool uses API server bundled with the SDK, which outputs lots of debugging info. You can suppress that with:

GO_APPENGINE_SDK/goapp test -v ./endpoints 2> /dev/null

Learn more about goapp tool.

go-endpoints's People

Contributors

adsouza avatar bashtian avatar broady avatar campoy avatar davidcv5 avatar dhermes avatar dsymonds avatar jittuu avatar jonprice avatar lorenzleutgeb avatar maxhawkins avatar philips avatar rakyll avatar riannucci avatar ritoon avatar vegacom avatar x1ddos avatar zboralski avatar zombiezen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-endpoints's Issues

Slices not supported in fields

Fields of type []string are not supported, adding the field Strings []string to DummyMsg makes many tests fail with the error:

--- FAIL: TestAPIDescriptor (0.00 seconds)
    apiconfig_test.go:135: createDescriptor: error creating descriptor: Unsupported field: &reflect.StructField{Name:"Strings", PkgPath:"", Type:(*reflect.rtype)(0x282a40), Tag:"", Offset:0xa0, Index:[]int{17}, Anonymous:false}

Fields of kind slice, chan, and others cause panic

Reported by @kylefinley

Requests with messages contain slices panic. Example:

type TestReq struct {
    Strings []string `json:"strings"`
}

func (s *Service) Test(c context.Context, req *TestReq) error {
    return nil
}
2015/07/29 19:30:21 http: panic serving 127.0.0.1:62097: runtime error: comparing uncomparable type []string
goroutine 6 [running]:
net/http.func·011()
    /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1130 +0xbb
github.com/GoogleCloudPlatform/go-endpoints/endpoints.validateField(0x3697c0, 0xc2080ee840, 0xd7, 0x4dcc60, 0x7, 0x0, 0x0, 0x85aa58, 0x3697c0, 0x5054b0, ...)
    /dev/go/src/github.com/GoogleCloudPlatform/go-endpoints/endpoints/apiconfig.go:773 +0x27e
github.com/GoogleCloudPlatform/go-endpoints/endpoints.validateRequest(0x3633a0, 0xc2080ee840, 0x0, 0x0)
    /dev/go/src/github.com/GoogleCloudPlatform/go-endpoints/endpoints/apiconfig.go:760 +0x438
github.com/GoogleCloudPlatform/go-endpoints/endpoints.(*Server).ServeHTTP(0xc20807ffc0, 0x85c528, 0xc208044d20, 0xc208033520)
    /dev/go/src/github.com/GoogleCloudPlatform/go-endpoints/endpoints/server.go:151 +0x937
net/http.(*ServeMux).ServeHTTP(0xc20803a690, 0x85c528, 0xc208044d20, 0xc208033520)
    /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1541 +0x17d
appengine_internal.handleFilteredHTTP(0x85c528, 0xc208044d20, 0xc208033520)
    /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/appengine_internal/api_dev.go:98 +0x413
net/http.HandlerFunc.ServeHTTP(0x5dc048, 0x85c528, 0xc208044d20, 0xc208033520)
    /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1265 +0x41
net/http.serverHandler.ServeHTTP(0xc2080421e0, 0x85c528, 0xc208044d20, 0xc208033520)
    /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1703 +0x19a
net/http.(*conn).serve(0xc208044c80)
    /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1204 +0xb57
created by net/http.(*Server).Serve
    /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1751 +0x35e
INFO     2015-07-29 19:30:21,200 module.py:809] default: "POST /_ah/spi/Service.Test HTTP/1.1" 500 2399
INFO     2015-07-29 19:30:21,201 module.py:809] default: "PUT /_ah/api/test/v1/test?alt=json HTTP/1.1" 500 2490
INFO     2015-07-29 19:33:02,482 module.py:442] [default] Detected file changes:

Any ideas on what might be causing this. Thanks!

Session handling with go-endpoints ?

Hey guys !!!

I'm trying to implement Session handling and combine it with the go-endpoints package !

The package that i use to handle the session is Gorilla Sessions (github.com/gorilla/sessions), i would like some help..

I'm able to store a cookie to the client .. and when i call the endpoints is can see that the cookie is sent to the server.

The problem while i try to get the Session values from the Session storage while the api is called, i cant get threw to the cookie .. it seams that the endpoints package strip the http.Request from extra content or something .. ?

The place that i try to get the cookie is in the Server.go at the

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request){

var store = sessions.NewCookieStore([]byte("secret123"));
session, _ := store.Get(r, "session-name");
// Get the previously flashes, if any.
c.Infof("foo value is : %v",r.Cookies());
if flashes := session.Flashes(); len(flashes) > 0 {
// Just print the flash values.
c.Infof("this is the testing post message with cookie from the ServeHTTP : %v",flashes);
} else {
// Set a new flash.
session.AddFlash("Hello, flash messages world!")
c.Infof("No flashes found.");
}
session.Save(r, w)

}

what i get is a empty array .... :(

someone has a lead ?

THANKS !!!!!

Support anonymous (embedded) structs

The SPI request body that is generated by Go Endpoints seems to name the anonymously embedded struct, rather than actually embedding the fields of the inner struct in the outer struct, and because of this, JSON unmarshalling of the request struct is not working correctly.

type Inner struct {
  Name string `json:"name"`
}

type Outer struct {
  Inner
}

results in

{"Inner": {"name": "..."}}

It should result in

{"name": "..."}

More friendly API discovery methods

For instance,

api.MethodByName("SayHello").
    Get().  // or HTTPMethod("GET")
    Path("/hello").
    Scopes("one", "two").
    ClientIDs("some-client-id").
    Desc("A method that says hello")

Also, api.MethodByName should panic if no such method exists.

Same parameter in path and request body?

What happens if I have the same parameter in the request path and request body? I ask because it may be relevant for a request like this:

type User struct {
  Name string `json:"name"`
}

Service method/path: PATCH /users/{name}

PATCH /users/test1
{
  "name": "test2"
}

Does one of these always win?

Request body is always empty

Hi!

I'm trying to add some extra field in the request which are not part of the message request definition like what bossylobster suggested here, but I'm always getting an empty request body. Apparently, the request body is read but not restored to its original content when passed to service methods.

EDIT: Another way of adding "hidden" fields would be to add another endpoints tag "-" which will allow tagged fields to be ignored by endpoints and yet still be unpacked if it is added in the request.

Not exporting types Gives horrid results -- crash

While the Endpoints handler is parsing all the info I gave it, if it finds a problem, such as not capitalizing either a Request or Response type, this kind of error is given, rather than something a bit more meaningful.

The line in my code is a api.MethodByName("").Info() request.

ERROR 2014-10-08 18:58:27,799 http_runtime.py:281] bad runtime process port ['']
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x28 pc=0x2bea3]

goroutine 1 [running]:
runtime.panic(0x2d08e0, 0x6a56b9)
/private/var/folders/zj/06c51mbs71z4r22r59jzffjm003chb/T/appengine/go_appengine/goroot/src/pkg/runtime/panic.c:266 +0xb6
main19353.init·1()
aendpoints.go:98 +0x583
main19353.init()
_extra_imports_1.go:7 +0x51
main.init()
_go_main.go:18 +0x3d

goapp get -u github.com/crhym3/go-endpoints/endpoints

goapp get -u github.com/crhym3/go-endpoints/endpoints
package github.com/crhym3/go-endpoints/endpoints
    imports code.google.com/p/goprotobuf/proto: directory "/home/gert/go_appengine/goroot/src/pkg/code.google.com/p/goprotobuf/proto" is not using a known version control system

Can this be solved some how?

Get user information from the id_token or oauth token in the request

Currently, the only way to get the user associated with a request is to use appengine/user package:

ctx := appengine.NewContext(req)
user.CurrentOAuth(ctx, "some.scope")

An endpoints.CurrentUser(ctx, scopes) method should probably wrap user.CurrentOAuth and do some additional checking, i.e. similar to what's happening in python land: https://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/endpoints/users_id_token.py?spec=svn345&r=345

Go 1.5 compatibility (internal/* package visibility)

Attempting to build go-endpoints with 1.5 fails:

=> Fetching dependencies for github.com/GoogleCloudPlatform/go-endpoints/endpoints...
package github.com/GoogleCloudPlatform/go-endpoints/endpoints
imports google.golang.org/appengine/internal: use of internal package not allowed
package github.com/GoogleCloudPlatform/go-endpoints/endpoints
imports google.golang.org/appengine/internal/user: use of internal package not allowed

Field tags not working

Hi!

I'm trying to compare the behavior of python endpoints messages to request field tags, and I'm getting different results.

In python endpoints, when a required field does not have a value, the response would be a 400 Bad Request Error (and the service method would not be executed) while in the current implementation I'm getting an OK response (the service method is executed).

The default, min, and max tags are also not working.

Inquiring the android publisher API

I'm having an issue with inquiring the android publisher API i tried several ways but i'm stuck completely...
i tried this way but i got a 401 HTTP

c := endpoints.NewContext(r)
    st := []string{subUrl, userReq.SubscriptionToken}

    cli := &http.Client{
        Transport: &oauth2.Transport{
            Source: google.AppEngineTokenSource(c, "https://www.googleapis.com/auth/androidpublisher"),
            Base: &urlfetch.Transport{Context: c, Deadline: 0,
                AllowInvalidServerCertificate: true},
        },
    }

    res, err := cli.Get(strings.Join(st, "")) 

When i tried a similar code with a different scop against the cloud storage things worked fine ...

Im thinking of another way as suggested here https://developers.google.com/android-publisher/authorization
And passing the access token as query param.
How can i get the value of the access token ?

thanks,
miki

Package Not Go-Gettable

I've been having trouble integrating my go-endpoints project with godep because of the appengine/... dependencies. It would be nice if you could "go get" install go-endpoints.

Do you think it would be possible to put the appengine-specific stuff behind a build flag?

Cannot add a slice field in request

I'm getting an Unsupported field error when adding a slice in a request.

EDIT: I'm only encountering this when using GET as the HTTP method when registering services.

slices still not supported in fields

related: #57

I haven't managed to get slices working in the request (got them working in the response).

For the github example you provide. I got the List() method working for the greeting service. This returns a GreetingsList method which contains a list of greetings.

However, I was unable to get the GreetingsList to be the request, see my modified function:

func (gs *GreetingService) List(c endpoints.Context, r *GreetingsList) (*GreetingsList, error) {
    return r, nil
}

In the function above we get:

2015/03/05 02:29:01 ERROR: Unsupported field: &reflect.StructField{Name:"Items", PkgPath:"", Type:(*reflect.rtype)(0x2c4a80), Tag:"json:\"items\"", Offset:0x0, Index:[]int{0}, Anonymous:false}

greetings and greetings list are as follows:

// Greeting is a datastore entity that represents a single greeting.
// It also serves as (a part of) a response of GreetingService.
type Greeting struct {
  Key     *datastore.Key `json:"id" datastore:"-"`
  Author  string         `json:"author"`
  Content string         `json:"content" datastore:",noindex" endpoints:"req"`
  Date    time.Time      `json:"date"`
}

// GreetingsList is a response type of GreetingService.List method
type GreetingsList struct {
  Items []*Greeting `json:"items"`
}

For me I'm wanting to use a list of strings in my request. e.g. Strings []string.

Is there something wrong i'm doing - or is this a bug?

thanks

Generate signed URL

Hey ,
I thinking to create a signed url func that will return the URL to the client and he will upload and download the files directly from Cloud storage.
I used those link as reference
1.https://cloud.google.com/storage/docs/access-control#signing-code-go
2.https://github.com/GoogleCloudPlatform/gcloud-golang/blob/master/storage/storage.go
I'm looking to use the &storage.SignedURLOptions method
My only issue is how can i generate the private key on the cloud endpoints framework
Can i save the pem file somewhere ?

JSON Unmarshal not handling IOS client POST

The Javascript client via API Explorer posts a plain JSON object

{"key" : "value", "key2" : value2}

but the IOS client posts a JSON RPC with the same data wrapped inside a larger object

{
  "method" : "xxxxx",
  "id" : "gtl_3",
  "jsonrpc" : "2.0",
  "params" : {
    "resource" : {
      "key" : "value", 
      "key2" : value2
    }
  },
  "apiVersion" : "v1"
}

In server.go, the request body in the first case works but in the second case cannot be Unmarshal by JSON.

Should go-endpoints be able to handle both cases currently?

The regexp curlyBrackets used for Duplicate method detection is greedy matching

In the APIDescriptor function in apiconfig.go there is checking for duplicate methods.

If you have the following

/object1/{id}

and

/object1/{id}/object2{id2}

the both get matched as the same thing because the curlyBrackets regex is greedy matching /object1/{id}/object2{id2} to /object1/{} instead of /object1/{}/object2{} i.e. .+ is matching to the text id}/object2{id2

Param values conversion for SPI input on dev server (json: cannot unmarshal error)

Having something like the following as an input request type of a service method:

type SomeRequest struct {
  Param1 int32
  Param2 float32
  Param3 float64
  Param4 bool
}

and an API path template "do/something/{param1}/{param2}/{param3}", a request like this:

GET /_ah/api/myapi/v1/do/something/1/2/3/?param4=true

will result in an error similar to: json: cannot unmarshal string into Go value of type int.

This is happening because dev server is not currently converting int32, floats32/64 and bools to their "real" values (i.e. they are seen as strings).

A simple workaround (only for dev, production works correctly!) is to add json:",string" to the field tags:

type SomeRequest struct {
  Param1 int32    `json:",string"`
  Param2 float32  `json:",string"`
  Param3 float64  `json:",string"`
  Param4 bool     `json:",string"`
}

This is not really a bug in endpoints code. I'm posting it here in case someone bumps into this.

dev_appserver crashes after go get

dev_appserver crashes after I go get and it pulls down the crhym3/go-endpoints repo. If I remove the go-endpoints.appspot.com and tictactoeapp directories it works again. Perhaps the example applications need to be moved into separate repos?

INFO     2013-06-02 04:43:43,331 sdk_update_checker.py:244] Checking for updates to the SDK.
INFO     2013-06-02 04:43:43,541 sdk_update_checker.py:288] This SDK release is newer than the advertised release.
WARNING  2013-06-02 04:43:43,545 api_server.py:328] Could not initialize images API; you are likely missing the Python "PIL" module.
INFO     2013-06-02 04:43:43,547 api_server.py:152] Starting API server at: http://127.0.0.1:58323
INFO     2013-06-02 04:43:43,550 dispatcher.py:150] Starting server "default" running at: http://localhost:8080
INFO     2013-06-02 04:43:43,553 admin_server.py:117] Starting admin server at: http://localhost:8000
panic: http: multiple registrations for /_ah/spi/

goroutine 1 [running]:
net/http.(*ServeMux).Handle(0xf840090900, 0x2f7d6c, 0x9, 0xf84012c930, 0xf84010dd40, ...)
        /private/var/folders/00/0jth8000h01000cxqpysvccm0027_1/T/appengine/google_appengine/goroot/src/pkg/net/http/server.go:957 +0x1ac
github.com/crhym3/go-endpoints/endpoints.(*Server).HandleHttp(0xf84010dd40, 0xf840090900, 0x28984, 0x1cd7c0)
        src/github.com/crhym3/go-endpoints/endpoints/server.go:120 +0x7b
github.com/crhym3/go-endpoints/endpoints.HandleHttp()
        src/github.com/crhym3/go-endpoints/endpoints/server.go:219 +0x31
main65498.init·1()
        core-update.go:42 +0x1bc
main65498.init()
        admin.go:132 +0x7c
main.init()
        _go_main.go:0 +0x40

goroutine 2 [syscall]:
created by runtime.main
        /private/var/folders/00/0jth8000h01000cxqpysvccm0027_1/T/appengine/google_appengine/goroot/src/pkg/runtime/proc.c:221
ERROR    2013-06-02 04:43:46,645 http_runtime.py:221] unexpected port response from runtime ['']; exiting the development server
INFO     2013-06-02 04:43:47,579 api_server.py:518] Applying all pending transactions and saving the datastore
INFO     2013-06-02 04:43:47,579 api_server.py:521] Saving search indexes

Calling Print functions using fmt in init()

WhenPrint methods from fmt are called during the init()
For e.g in samples/helloworld/helloworld.go, the API Service discovery fails.
http://localhost:8080/_ah/api/discovery/v1/apis
returns

{"error": {"message": "BackendService.getApiConfigs Error"}}

This also disables functionality of the api explorer
http://localhost:8080/_ah/api/explorer

init() from the helloworld.go

func init() {

    api, err := endpoints.RegisterService(&GreetingService{},
        "greetings", "v1", "Greetings API", true)
    if err != nil {
        log.Fatalf("Register service: %v", err)
    } else {
        log.Printf("API registered %v", api)
    }
    endpoints.HandleHTTP()
}

works but the following init() fails

func init() {

    api, err := endpoints.RegisterService(&GreetingService{},
        "greetings", "v1", "Greetings API", true)
    if err != nil {
        log.Fatalf("Register service: %v", err)
    } else {
        fmt.Printf("API registered %v", api)
    }
    endpoints.HandleHTTP()
}

Support for managed VMs

Hi!

I'm currently using a ported version (I just changed appengine.Context to context.Context and logging codes such as c.Debugf(...) to google.golang.org/appengine/log methods) so that I can use endpoints on managed VMs, but it would be great if managed VMs can be officially supported. Is there any time frame on when it would be supported?

Use tokeninfo API for Bearer token validation in dev_appserver

Use tokeninfo API for Bearer token validation in dev_appserver.

When appengine.IsDevAppServer() is true, we can make a POST to

https://www.googleapis.com/oauth2/v2/tokeninfo?access_token=$TOKEN

to actually get the current user from the token instead of using the dummy user returned from the user package in dev_appserver.

The $TOKEN can be parsed from the Authorization header of the request.

NOTE: AFAICT r.Header.Get is case-insensitive, e.g. r.Header.Get("authorization") and r.Header.Get("Authorization") produce the same value. This should be true, but I couldn't find it in the doc. Do you know?

Memcache for cert

https://github.com/GoogleCloudPlatform/go-endpoints/blob/master/endpoints/auth.go#L191
namespacedContext, err := appengine.Namespace(c, certNamespace)
// The certNamespace is static "__verify_jwt"

https://github.com/GoogleCloudPlatform/go-endpoints/blob/master/endpoints/auth.go#L198
_, err = memcache.JSON.Get(namespacedContext, DefaultCertURI, &certs)
The DefaultCertURI is static "https://www.googleapis.com/service_accounts/v1/metadata/raw/[email protected]"

Different user will save and get their cert in the same memcache.

Please let me know if I am wrong. Thanks in advance.

goapp get -u github.com/crhym3/go-endpoints/endpoints -- ERROR

package github.com/crhym3/go-endpoints/endpoints
imports code.google.com/p/goprotobuf/proto: directory "/Users/lesv/google-cloud-sdk/platform/google_appengine/goroot/src/pkg/code.google.com/p/goprotobuf/proto" is not using a known version control system

I tried this on two machines.

appengine/user

How do you make the api explorer oauth2 work for endpoints? (scope https://www.googleapis.com/auth/userinfo.email )

func (gs *GreetingService) Store(r *http.Request, req *Request, resp *Response) error {
    c := appengine.NewContext(r)
    u := user.Current(c)
    if u != nil {c.Infof("Hello, %v\n", u)}
    if u != nil {fmt.Printf("Hello, %v\n", u)}
}

u is always nil, in java I had to add something like this to make it work.

@Api(name = "rest1",
     version = "0",
     scopes = {Id.EMAIL_SCOPE},
     clientIds = {Id.WEB_CLIENT_ID, Id.ANDROID_CLIENT_IDd, Id.ANDROID_CLIENT_IDr, Id.EXPLORER_ID},
     audiences = {Id.ANDROID_AUDIENCE})

Prefix structs from different packages

Currently, structs are all mapped to the same namespace in the SPI document even if they are from different packages in Go.

For example, if I have a struct named Msg in the chat package and another struct that is also named Msg in the user package, there would be a name conflict when the SPI document is generated.

appengine.Namespace

Can this be implemented in endpoints?

When I do the following my datastore index breaks

c := endpoints.NewContext(r)
c2, err := appengine.Namespace(c, "")
if err != nil {return err}

filtered or ordered queries do not work anymore on appspot.com they only work on localhost:8080

Pointer to string, int*, etc not supported

A request or a response with pointers as fields are currently not supported. When a request A is used, Go endpoints fails with error: "Unsupported type ... of property ..."

type A struct {
B *string
}

I have a working patch I would likely send soon for review.

Thanks,

RegisterServiceWithDefaults doesn't work

Hello,

I haven't found an example using this method, so I tried by my self. But it doesn't work.

 ptxService := &PtxService{}
    ptzService := &PtzService{}
  apiPtx, err := endpoints.RegisterService(ptxService, "ptx", "v1", "Ptx API", true)
  if err != nil {
    panic(err.Error())
  }
  apiPtz, err := endpoints.RegisterServiceWithDefaults(ptzService)
    if err != nil {
        panic(err.Error())
    }

    registerPtx := func(orig, name, method, path, desc string) {
      m := apiPtx.MethodByName(orig)
      if m == nil {
        panic("No methods found.")
      }
      i := m.Info()
      i.Name, i.HTTPMethod, i.Path, i.Desc = name, method, path, desc
  }

  registerPtz := func(orig, name, method, path, desc string) {
      m := apiPtz.MethodByName(orig)
      if m == nil {
        panic("No methods found.")
      }
      i := m.Info()
      i.Name, i.HTTPMethod, i.Path, i.Desc = name, method, path, desc
  }

  registerPtx("Connect", "connect", "GET", "connect", "Connect.")
    registerPtz("Estimation", "ptz.estimation", "GET", "ptz/estimation", "Get some informations.")

  endpoints.HandleHTTP()

It's a bug, or I'm missing something?

panic: endpoints: "DumpsterAPI" has no exported methods of suitable type

Hey i have a wired issue with register this method

func (s *DumpsterAPI) LoginUser(c endpoints.Context, userReq Users) (userRes Users, err error) {

    c.Debugf("in the LoginUser method")

    user := userManger.login(userReq) //return a Users Type

    return user, nil
}

This is how im trying to register it but im getting the panic instead


func RegisterService() (*endpoints.RPCService, error) {
    api := &DumpsterAPI{}
    rpcService, err := endpoints.RegisterService(api,
        "cloud", "v1", "baloota API", true)

    if err != nil {
        return nil, err
    }

    register := func(orig, name, method, path, desc string) {
        m := rpcService.MethodByName(orig)

        if m == nil {
            log.Fatalf("Missing method %s", orig)
        }
        i := m.Info()
        i.Name, i.HTTPMethod, i.Path, i.Desc, i.Scopes, i.ClientIds, i.Audiences =
            name, method, path, desc, scopes, clientIds, audiences
    }
    register("LoginUser", "LoginUser", "POST", "login", "login to app")

    return rpcService, nil

api method taking struct from wrong package

I have this code which works perfectly:

package api
import (
    "github.com/GoogleCloudPlatform/go-endpoints/endpoints"
    "github.com/robert-king/studentcoursereview/backends/gopackages/course"
    "log"
)
type Course2 struct {
    DomainName string `json:"domainName" endpoints:"req,desc=name of domain or university"`
    CourseGroup string `json:"courseGroup" endpoints:"req,desc=name of course group e.g. biosci"`
    CourseName string `json:"courseName" endpoints:"req,desc=name of course e.g. biosci101"`
    CourseTitle string `json:"courseTitle" endpoints:"req,desc=course title or empty string"`
}

func (sa *ScrApi) CreateCourse(c endpoints.Context, course_ *Course2) (error) {
    return course.CreateCourse(c,course_.DomainName, course_.CourseGroup, course_.CourseName, course_.CourseTitle)
}

...

register("CreateCourse", "createCourse", "POST", "createCourse", "createCourse")

I have another package called course. Inside course I have a different struct called Course.
If I rename "Course2" to be "Course". Then in the api explorer & client will for some reason expect the Course struct from the course package rather than the Course struct from the api package which breaks everything. Furthermore renaming "Course" to "Course3" in the course package, and renaming "Course2" to Course" in the api package fixed things - so basically the struct name in a different package can break the api.
Cheers.

Returning custom HTTP code

Hey ,

I want to return a HTTP custom code ,now for each success request im getting HTTP 200
I cant figure out were the http.StatusOK is set?
What will be the correct way to implement it without breaking something...

Allow different service method signatures

// this is how it is right now
func (Service) SayHello(r *http.Request, req *Request, res *Response) error {}

// *Response is created within the method
func (Service) SayHello(r *http.Request, req *Request) (*Response, error) {}

// This method doesn't need the original *http.Request
func (Service) SayHello(req *Request) (*Response, error) {}

// The original request can be retrieved with c.HTTPRequest()
func (Service) SayHello(c endpoints.Context, req *Request) (*Response, error) {}

json tags validation

Hi ,
In the struct usage example , you use the endpoints:"req"`
that suppose to be a mandatory field ?
I tried to pass an empty value to a field with the endpoints:req tag and i didn't get any error
What will be the best way to valid mandatory fields ?

i can do something like that but it must be a nicer solution

if len(subscriptionToken) == 0 {
        return endpoints.NewAPIError("subscriptionToken is empty", "subscriptionToken is empty", 400)
    }

Can't go get github.com/crhym3/go-endpoints/endpoints

It'll fail on importing appengine packages:

alexmac:~ gopher$ go get github.com/crhym3/go-endpoints/endpoints
package appengine: unrecognized import path "appengine"
package appengine/user: unrecognized import path "appengine/user"
package appengine_internal/user: unrecognized import path "appengine_internal/user"

I guess there's no easy way to fix this for now so I'll probably have to just update the readme with a how-to-install info and say that "go get" won't work for now.

Check Bearer token enhancement

Once hit the https://github.com/GoogleCloudPlatform/go-endpoints/blob/master/endpoints/auth.go#L561

2015/03/03 03:42:03 DEBUG: Checking for Bearer token.

2015/03/03 03:42:03 DEBUG: Fetching token info from "https://www.googleapis.com/oauth2/v2/tokeninfo?access_token=ya29.KwEtOQxqd6gtDFV2WsqJgtwfrtiVg53C4_m6a8U710y5l6z1bb5Rrwi-D5t53-P63H6ptG_XNoyQig"
2015/03/03 03:42:04 DEBUG: Tokeninfo replied with 200 OK

2015/03/03 03:42:04 DEBUG: Fetching token info from "https://www.googleapis.com/oauth2/v2/tokeninfo?access_token=ya29.KwEtOQxqd6gtDFV2WsqJgtwfrtiVg53C4_m6a8U710y5l6z1bb5Rrwi-D5t53-P63H6ptG_XNoyQig"
2015/03/03 03:42:04 DEBUG: Tokeninfo replied with 200 OK

first urlfetch : endpoints/context_dev.go func CurrentOAuthClientID -> getScopedTokeninfo
second urlfetch : endpoints/context_dev.go func CurrentOAuthUser -> getScopedTokeninfo

Urlfetch the the same url twice with same result.

It become very slow.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.