Skip to content

Commit

Permalink
support batch api now.
Browse files Browse the repository at this point in the history
  • Loading branch information
huandu committed Oct 21, 2012
1 parent ab6b0cd commit c16e39c
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 20 deletions.
82 changes: 63 additions & 19 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,33 +250,46 @@ func (app *App) SessionFromSignedRequest(signedRequest string) (session *Session

// Makes a facebook graph api call.
//
// It's a wrapper of App.Api(). Only works for graph api that doesn't require
// It's a wrapper of Session.Api(). Only works for graph api that doesn't require
// app id, app secret and access token. Can be called in multiple goroutines.
//
// If app id, app secret or access token is required in graph api, caller should use
// New() to create a new facebook instance instead.
// New() to create a new facebook session through App instead.
func Api(path string, method Method, params Params) (Result, error) {
return defaultSession.Api(path, method, params)
}

// Makes a batch facebook graph api call.
//
// It's a wrapper of Session.Api(). Only works for graph api that doesn't require
// app id, app secret and access token. Can be called in multiple goroutines.
//
// If app id, app secret or access token is required in graph api, caller should use
// New() to create a new facebook session through App instead.
func BatchApi(accessToken string, params ...Params) ([]Result, error) {
return defaultSession.graphBatch(accessToken, params...)
}

// Makes a facebook graph api call.
//
// Returns facebook graph api call result.
// If facebook returns error in response, returns error details in res and set err.
func (session *Session) Api(path string, method Method, params Params) (Result, error) {
res, err := session.graph(path, method, params, false)
res, err := session.graph(path, method, params)

if res != nil {
return res.(map[string]interface{}), err
return res, err
}

return nil, err
}

func (session *Session) BatchApi(params Params) (BatchResult, error) {
res, err := session.graph("/", "POST", params, true)
if res != nil {
return res.([]interface{}), err
}
return nil, err
// Makes a batch call. Each params represent a single facebook graph api call.
// See https://developers.facebook.com/docs/reference/api/batch/ for batch call api details.
//
// Returns an array of batch call result on success.
func (session *Session) BatchApi(params ...Params) ([]Result, error) {
return session.graphBatch(session.accessToken, params...)
}

// Gets current user id from access token.
Expand Down Expand Up @@ -329,8 +342,9 @@ func (session *Session) App() *App {
return session.app
}

func (session *Session) graph(path string, method Method, params Params, batch bool) (res interface{}, err error) {
func (session *Session) graph(path string, method Method, params Params) (res Result, err error) {
var graphUrl string
var response []byte

if params == nil {
params = Params{}
Expand All @@ -345,7 +359,7 @@ func (session *Session) graph(path string, method Method, params Params, batch b
graphUrl = getUrl("graph", path, nil)
}

response, err := session.oauthRequest(graphUrl, params)
response, err = session.oauthRequest(graphUrl, params)

// cannot get response from remote server
if err != nil {
Expand All @@ -361,10 +375,40 @@ func (session *Session) graph(path string, method Method, params Params, batch b
}

// facebook returns an error
if(!batch) {
if _, ok := res.(map[string]interface{})["error"]; ok {
err = fmt.Errorf("facebook returns an error")
}
if _, ok := res["error"]; ok {
err = fmt.Errorf("facebook returns an error")
}

return
}

func (session *Session) graphBatch(accessToken string, params ...Params) (res []Result, err error) {
var batchParams = Params{"access_token": accessToken}
var batchJson []byte
var response []byte

// encode all params to a json array.
batchJson, err = json.Marshal(params)

if err != nil {
return
}

batchParams["batch"] = string(batchJson)

graphUrl := getUrl("graph", "", nil)
response, err = session.oauthRequest(graphUrl, batchParams)

if err != nil {
return
}

err = json.Unmarshal(response, &res)

if err != nil {
res = nil
err = fmt.Errorf("cannot format facebook batch response. %v", err)
return
}

return
Expand All @@ -387,15 +431,15 @@ func (session *Session) makeRequest(url string, params Params) ([]byte, error) {
return nil, fmt.Errorf("cannot reach facebook server. %v", err)
}

buf = &bytes.Buffer{}
_, err = io.Copy(buf, response.Body)
response.Body.Close()
defer response.Body.Close()

if response.StatusCode >= 300 {
return nil, fmt.Errorf("facebook server response an HTTP error. code: %v, body: %s",
response.StatusCode, string(buf.Bytes()))
}

buf = &bytes.Buffer{}
_, err = io.Copy(buf, response.Body)

if err != nil {
return nil, fmt.Errorf("cannot read facebook response. %v", err)
Expand Down
27 changes: 26 additions & 1 deletion facebook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const (
FB_TEST_MY_USERNAME = "huan.du"

// remeber to change it to a valid token to run test
//FB_TEST_VALID_ACCESS_TOKEN = "AAACZA38ZAD8CoBABo4ZA4l5bGDSneBx9omVlVMNpxErbV0cLF5vl5dVqtx8U8QOYdmD4TAvZAWSL4gMGe4zrMOgjMELqqZBdTeU5bJfj8ygZDZD"
//FB_TEST_VALID_ACCESS_TOKEN = "AAACEdEose0cBAEVR6GZAEcja9ZBIdmYrF4I7nAFFbYZAe9tdYEv6uZCHGPpPFcbNYo49ya6qmAChPUZBO2UYmotTdWiDZBMQZCGXm8lA9qjCQZDZD"
FB_TEST_VALID_ACCESS_TOKEN = ""

// remember to change it to a valid signed request to run test
Expand Down Expand Up @@ -72,6 +72,31 @@ func TestApiGetUserInfo(t *testing.T) {
t.Logf("my info. %v", me)
}

func TestBatchApiGetInfo(t *testing.T) {
if FB_TEST_VALID_ACCESS_TOKEN == "" {
t.Logf("cannot call batch api without access token. skip this test.")
return
}

params1 := Params{
"method": GET,
"relative_url": FB_TEST_MY_USERNAME,
}
params2 := Params{
"method": GET,
"relative_url": uint64(100002828925788), // id of my another facebook id
}

me, err := BatchApi(FB_TEST_VALID_ACCESS_TOKEN, params1, params2)

if err != nil {
t.Errorf("cannot get batch result. [e:%v]", err)
return
}

t.Logf("my info. %v", me)
}

func TestApiParseSignedRequest(t *testing.T) {
if FB_TEST_VALID_SIGNED_REQUEST == "" {
t.Logf("skip this case as we don't have a valid signed request.")
Expand Down

0 comments on commit c16e39c

Please sign in to comment.