# Introduction

![Build Status](https://koltyakov.visualstudio.com/SPNode/_apis/build/status/gosip?branchName=master) [![Go Report Card](https://goreportcard.com/badge/github.com/koltyakov/gosip)](https://goreportcard.com/report/github.com/koltyakov/gosip) [![codecov](https://codecov.io/gh/koltyakov/gosip/branch/master/graph/badge.svg)](https://codecov.io/gh/koltyakov/gosip) [![License](https://img.shields.io/github/license/koltyakov/gosip.svg)](https://github.com/koltyakov/gosip/blob/master/LICENSE) [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)

![](https://1703766770-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lxeh2bcyJEYmD6z58mf%2F-LxeiSkPDZ1cjV1RmmZJ%2F-Lxep0QlsK2R-f-E51AH%2Fgosip.png?alt=media\&token=7b8ef2cd-e28e-4ac3-a4b8-f049db5e9a0c)

## Main features

* Unattended authentication using different strategies.
* [Fluent API](https://go.spflow.com/api/fluent) syntax for SharePoint object model.
* Simplified API consumption (REST, CSOM, SOAP, etc.).
* SharePoint-aware embedded features (retries, header presets, error handling).

### Supported SharePoint versions

* SharePoint Online (SPO).
* On-Premises (2019/2016/2013).

### Supported auth strategies

* SharePoint Online:
  * [Azure Certificate (App Only)](https://go.spflow.com/auth/strategies/azure-certificate-auth)
  * [Azure Username/Password](https://go.spflow.com/auth/strategies/azure-creds-auth)
  * [SAML](https://go.spflow.com/auth/strategies/saml) based with user credentials
  * [Add-In only](https://go.spflow.com/auth/strategies/addin) permissions
  * ADFS user credentials (automatically detects in [SAML](https://go.spflow.com/auth/strategies/saml) strategy)
  * [Azure Device flow](https://go.spflow.com/auth/strategies/azure-device-flow)
  * [On-Demand authentication](https://go.spflow.com/auth/strategies/on-demand)
* SharePoint On-Premises 2019/2016/2013:
  * [User credentials](https://go.spflow.com/auth/strategies/ntlm) (NTLM)
  * [ADFS user credentials](https://go.spflow.com/auth/strategies/adfs) (ADFS, WAP -> Basic/NTLM, WAP -> ADFS)
  * Behind a reverse proxy ([Forefront TMG](https://go.spflow.com/auth/strategies/tmg), [WAP -> Basic/NTLM](https://go.spflow.com/auth/strategies/adfs), [WAP -> ADFS](https://go.spflow.com/auth/strategies/adfs))
  * [Form-based authentication](https://go.spflow.com/auth/strategies/fba) (FBA)
  * [On-Demand authentication](https://go.spflow.com/auth/strategies/on-demand)

## Installation

```bash
go get github.com/koltyakov/gosip
```

## Usage insights

### Understand SharePoint environment type and authentication strategy

Let's assume it's SharePoint Online and Add-In Only permissions. Then `strategy "github.com/koltyakov/gosip/auth/addin"` sub package should be used.

```go
package main

import (
  "github.com/koltyakov/gosip"
  "github.com/koltyakov/gosip/api"
  strategy "github.com/koltyakov/gosip/auth/addin"
)
```

### Initiate authentication object

```go
auth := &strategy.AuthCnfg{
  SiteURL:      os.Getenv("SPAUTH_SITEURL"),
  ClientID:     os.Getenv("SPAUTH_CLIENTID"),
  ClientSecret: os.Getenv("SPAUTH_CLIENTSECRET"),
}
```

AuthCnfg's from different strategies contains different options relevant for a specified auth type.

The authentication options can be provided explicitly or can be read from a configuration file (see [more](https://go.spflow.com/auth/overview#authentication-strategies)).

```go
configPath := "./config/private.json"
auth := &strategy.AuthCnfg{}

err := auth.ReadConfig(configPath)
if err != nil {
  fmt.Printf("Unable to get config: %v\n", err)
  return
}
```

### Bind auth client with Fluent API

```go
client := &gosip.SPClient{AuthCnfg: auth}

sp := api.NewSP(client)

res, err := sp.Web().Select("Title").Get()
if err != nil {
  fmt.Println(err)
}

fmt.Printf("%s\n", res.Data().Title)
```

## Usage samples

### Fluent API client

Provides a simple way of constructing API endpoint calls with IntelliSense and chainable syntax.

```go
package main

import (
  "encoding/json"
  "fmt"
  "log"

  "github.com/koltyakov/gosip"
  "github.com/koltyakov/gosip/api"
  strategy "github.com/koltyakov/gosip/auth/addin"
)

func main() {
  // Getting auth params and client
  client, err := getAuthClient()
  if err != nil {
    log.Fatalln(err)
  }

  // Binding SharePoint API
  sp := api.NewSP(client)

  // Custom headers
  headers := map[string]string{
    "Accept": "application/json;odata=minimalmetadata",
    "Accept-Language": "de-DE,de;q=0.9",
  }
  config := &api.RequestConfig{Headers: headers}

  // Chainable request sample
  data, err := sp.Conf(config).Web().Lists().Select("Id,Title").Get()
  if err != nil {
    log.Fatalln(err)
  }

  // Response object unmarshalling
  // (struct depends on OData mode and API method)
  res := &struct {
    Value []struct {
      ID    string `json:"Id"`
      Title string `json:"Title"`
    } `json:"value"`
  }{}

  if err := json.Unmarshal(data, &res); err != nil {
    log.Fatalf("unable to parse the response: %v", err)
  }

  for _, list := range res.Value {
    fmt.Printf("%+v\n", list)
  }

}

func getAuthClient() (*gosip.SPClient, error) {
  configPath := "./config/private.spo-addin.json" // <- file with creds
  auth := &strategy.AuthCnfg{}
  if err := auth.ReadConfig(configPath); err != nil {
    return nil, fmt.Errorf("unable to get config: %v", err)
  }
  return &gosip.SPClient{AuthCnfg: auth}, nil
}
```

### Generic HTTP-client helper

Provides generic GET/POST helpers for REST operations, reducing amount of `http.NewRequest` scaffolded code, can be used for custom or not covered with a Fluent API endpoints.

```go
package main

import (
  "fmt"
  "log"

  "github.com/koltyakov/gosip"
  "github.com/koltyakov/gosip/api"
  strategy "github.com/koltyakov/gosip/auth/ntlm"
)

func main() {
  configPath := "./config/private.ntlm.json"
  auth := &strategy.AuthCnfg{}

  if err := auth.ReadConfig(configPath); err != nil {
    log.Fatalf("unable to get config: %v\n", err)
  }

  sp := api.NewHTTPClient(&gosip.SPClient{AuthCnfg: auth})

  endpoint := auth.GetSiteURL() + "/_api/web?$select=Title"

  data, err := sp.Get(endpoint, nil)
  if err != nil {
    log.Fatalf("%v\n", err)
  }

  // sp.Post(endpoint, []byte(body), nil) // generic POST

  // generic DELETE helper crafts "X-Http-Method"="DELETE" header
  // sp.Delete(endpoint, nil)

  // generic UPDATE helper crafts "X-Http-Method"="MERGE" header
  // sp.Update(endpoint, nil)

  // CSOM helper (client.svc/ProcessQuery)
  // sp.ProcessQuery(endpoint, []byte(body))

  fmt.Printf("response: %s\n", data)
}
```

### Low-level HTTP-client usage

Low-lever SharePoint-aware HTTP client from `github.com/koltyakov/gosip` package for custom or not covered with a Fluent API client endpoints with granular control for HTTP request, response, and `http.Client` parameters. Used internally but almost never required in a consumer code.

```go
client := &gosip.SPClient{AuthCnfg: auth}

var req *http.Request
// Initiate API request
// ...

resp, err := client.Execute(req)
if err != nil {
  fmt.Printf("Unable to request api: %v", err)
  return
}
```

SPClient has `Execute` method which is a wrapper function injecting SharePoint authentication and ending up calling `http.Client`'s `Do` method.

## Reference

Many auth flows have been "copied" from [node-sp-auth](https://github.com/s-kainet/node-sp-auth) library (used as a blueprint), which we intensively use in Node.js ecosystem for years.

Fluent API and wrapper syntax are inspired by [PnPjs](https://github.com/pnp/pnpjs) which is also the first-class citizen on almost all our Node.js and front-end projects with SharePoint involved.

## License

[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fkoltyakov%2Fgosip.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkoltyakov%2Fgosip?ref=badge_large)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://go.spflow.com/readme.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
