

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Menyesuaikan Permintaan Klien AWS SDK untuk Go v2 dengan Middleware
<a name="middleware"></a>

**Awas**  
 Memodifikasi pipeline permintaan klien dapat mengakibatkan permintaan yang salah bentuk/tidak valid, atau dapat mengakibatkan kesalahan aplikasi yang tidak terduga. Fungsionalitas ini dimaksudkan untuk kasus penggunaan lanjutan yang tidak disediakan oleh antarmuka SDK secara default. 

 [Anda dapat menyesuaikan permintaan AWS SDK untuk Go klien dengan mendaftarkan satu atau lebih middleware ke tumpukan operasi layanan.](https://pkg.go.dev/github.com/aws/smithy-go/middleware#Stack) Tumpukan terdiri dari serangkaian langkah: Initialize, Serialize, Build, Finalize, dan Deserialize. Setiap langkah berisi nol atau lebih middleware yang beroperasi pada jenis input dan output langkah itu. Diagram dan tabel berikut memberikan gambaran umum tentang bagaimana permintaan dan respons operasi melintasi tumpukan. 

 ![\[Middleware\]](http://docs.aws.amazon.com/id_id/sdk-for-go/v2/developer-guide/images/middleware.png) 


|  Langkah Tumpukan  |  Deskripsi  | 
| --- | --- | 
|  Inisialisasi  |  Mempersiapkan input, dan menetapkan parameter default sesuai kebutuhan.  | 
|  Serialisasi  |  Serialisasi input ke format protokol yang cocok untuk lapisan transport target.  | 
|  Membangun  |  Lampirkan metadata tambahan ke input serial, seperti HTTP Content-Length.  | 
|  Selesaikan  |  Persiapan pesan akhir, termasuk percobaan ulang dan otentikasi (penandatanganan SiGv4).  | 
|  Deserialisasi  |  Deserialisasi tanggapan dari format protokol menjadi tipe atau kesalahan terstruktur.  | 

 Setiap middleware dalam langkah tertentu harus memiliki pengidentifikasi unik, yang ditentukan oleh metode middleware. `ID` Pengidentifikasi middleware memastikan bahwa hanya satu contoh dari middleware tertentu terdaftar ke langkah, dan memungkinkan middleware langkah lain dimasukkan relatif terhadap itu. 

 Anda melampirkan middleware langkah dengan menggunakan langkah `Insert` atau `Add` metode. Anda gunakan `Add` untuk melampirkan middleware ke awal langkah dengan menentukan [middleware.Before sebagai [RelativePosition](https://pkg.go.dev/github.com/aws/smithy-go/middleware#RelativePosition), dan [middleware.After](https://pkg.go.dev/github.com/aws/smithy-go/middleware#After)](https://pkg.go.dev/github.com/aws/smithy-go/middleware#Before) untuk melampirkan ke akhir langkah. Anda gunakan `Insert` untuk melampirkan middleware ke langkah dengan memasukkan middleware relatif terhadap middleware langkah lain. 

**Awas**  
 Anda harus menggunakan `Add` metode ini untuk memasukkan middleware langkah kustom dengan aman. Menggunakan `Insert` menciptakan ketergantungan antara middleware kustom Anda, dan middleware yang Anda masukkan relatif terhadap. Middleware dalam langkah tumpukan harus dianggap buram untuk menghindari perubahan yang melanggar yang terjadi pada aplikasi Anda. 

## Menulis Middleware Kustom
<a name="writing-a-custom-middleware"></a>

 Setiap langkah tumpukan memiliki antarmuka yang harus Anda penuhi untuk melampirkan middleware ke langkah tertentu. Anda dapat menggunakan salah satu `StepMiddlewareFunc` fungsi yang disediakan untuk memenuhi antarmuka ini dengan cepat. Tabel berikut menguraikan langkah-langkah, antarmuka mereka, dan fungsi pembantu yang dapat digunakan untuk memenuhi antarmuka. 


|  Langkah  |  Antarmuka  |  Fungsi Pembantu  | 
| --- | --- | --- | 
|  Inisialisasi  |  [InitializeMiddleware](https://pkg.go.dev/github.com/aws/smithy-go/middleware#InitializeMiddleware)  |  [InitializeMiddlewareFunc](https://pkg.go.dev/github.com/aws/smithy-go/middleware#InitializeMiddlewareFunc)  | 
|  Membangun  |  [BuildMiddleware](https://pkg.go.dev/github.com/aws/smithy-go/middleware#BuildMiddleware)  |  [BuildMiddlewareFunc](https://pkg.go.dev/github.com/aws/smithy-go/middleware#BuildMiddlewareFunc)  | 
|  Serialisasi  |  [SerializeMiddleware](https://pkg.go.dev/github.com/aws/smithy-go/middleware#SerializeMiddleware)  |  [SerializeMiddlewareFunc](https://pkg.go.dev/github.com/aws/smithy-go/middleware#SerializeMiddlewareFunc)  | 
|  Selesaikan  |  [FinalizeMiddleware](https://pkg.go.dev/github.com/aws/smithy-go/middleware#FinalizeMiddleware)  |  [FinalizeMiddlewareFunc](https://pkg.go.dev/github.com/aws/smithy-go/middleware#FinalizeMiddlewareFunc)  | 
|  Deserialisasi  |  [DeserializeMiddleware](https://pkg.go.dev/github.com/aws/smithy-go/middleware#DeserializeMiddleware)  |  [DeserializeMiddlewareFunc](https://pkg.go.dev/github.com/aws/smithy-go/middleware#DeserializeMiddlewareFunc)  | 

 Contoh berikut menunjukkan bagaimana Anda dapat menulis middleware khusus untuk mengisi anggota Bucket dari panggilan `GetObject` API Amazon S3 jika tidak disediakan. Middleware ini akan direferensikan dalam contoh lanjutan untuk menunjukkan cara melampirkan middleware langkah ke tumpukan. 

```
import "github.com/aws/smithy-go/aws"
import "github.com/aws/smithy-go/middleware"
import "github.com/aws/aws-sdk-go-v2/service/s3"

// ...

var defaultBucket = middleware.InitializeMiddlewareFunc("DefaultBucket", func(
    ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
) (
    out middleware.InitializeOutput, metadata middleware.Metadata, err error,
) {
    // Type switch to check if the input is s3.GetObjectInput, if so and the bucket is not set, populate it with
    // our default.
    switch v := in.Parameters.(type) {
    case *s3.GetObjectInput:
        if v.Bucket == nil {
            v.Bucket = aws.String("amzn-s3-demo-bucket")
        }
    }

    // Middleware must call the next middleware to be executed in order to continue execution of the stack.
    // If an error occurs, you can return to prevent further execution.
    return next.HandleInitialize(ctx, in)
})
```

## Melampirkan Middleware ke Semua Klien
<a name="attaching-middleware-to-all-clients"></a>

 [Anda dapat melampirkan middleware langkah kustom Anda ke setiap klien dengan menambahkan middleware menggunakan `APIOptions` anggota tipe AWS.config.](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Config) Contoh berikut melampirkan `defaultBucket` middleware ke setiap klien yang dibangun menggunakan objek aplikasi Anda: `aws.Config` 

```
import "context"
import "github.com/aws/aws-sdk-go-v2/aws"
import "github.com/aws/aws-sdk-go-v2/config"
import "github.com/aws/aws-sdk-go-v2/service/s3"
import "github.com/aws/smithy-go/middleware"

// ...

cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
    // handle error
}

cfg.APIOptions = append(cfg.APIOptions, func(stack *middleware.Stack) error {
    // Attach the custom middleware to the beginning of the Initialize step
    return stack.Initialize.Add(defaultBucket, middleware.Before)
})

client := s3.NewFromConfig(cfg)
```

## Melampirkan Middleware ke Operasi Tertentu
<a name="attaching-middleware-to-a-specific-operation"></a>

 Anda dapat melampirkan middleware langkah kustom Anda ke operasi klien tertentu dengan memodifikasi `APIOptions` anggota klien menggunakan daftar argumen variadik untuk operasi. Contoh berikut melampirkan `defaultBucket` middleware ke pemanggilan operasi Amazon S3 tertentu: `GetObject` 

```
import "context"
import "github.com/aws/aws-sdk-go-v2/aws"
import "github.com/aws/aws-sdk-go-v2/config"
import "github.com/aws/aws-sdk-go-v2/service/s3"
import "github.com/aws/smithy-go/middleware"

// ...

// registerDefaultBucketMiddleware registers the defaultBucket middleware with the provided stack.
func registerDefaultBucketMiddleware(stack *middleware.Stack) error {
    // Attach the custom middleware to the beginning of the Initialize step
    return stack.Initialize.Add(defaultBucket, middleware.Before)
}

// ...

cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
    // handle error
}

client := s3.NewFromConfig(cfg)

object, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
    Key: aws.String("my-key"),
}, func(options *s3.Options) {
    // Register the defaultBucketMiddleware for this operation only
    options.APIOptions = append(options.APIOptions, registerDefaultBucketMiddleware)
})
```

## Melewati Metadata ke Tumpukan
<a name="passing-metadata-down-the-stack"></a>

 Dalam situasi tertentu, Anda mungkin menemukan bahwa Anda memerlukan dua atau lebih middleware untuk berfungsi bersama-sama dengan berbagi informasi atau status. [Anda dapat menggunakan [context.Context](https://golang.org/pkg/context/#Context) untuk meneruskan metadata ini dengan menggunakan middleware. WithStackValue](https://pkg.go.dev/github.com/aws/smithy-go/middleware#WithStackValue). `middleware.WithStackValue`melampirkan pasangan kunci-nilai yang diberikan ke konteks yang disediakan, dan dengan aman membatasi ruang lingkup ke tumpukan yang sedang dijalankan. [Nilai stack-scoped ini dapat diambil dari konteks menggunakan middleware. GetStackValue](https://pkg.go.dev/github.com/aws/smithy-go/middleware#GetStackValue)dan memberikan kunci yang digunakan untuk menyimpan nilai yang sesuai. Kunci harus sebanding, dan Anda harus mendefinisikan tipe Anda sendiri sebagai kunci konteks untuk menghindari tabrakan. Contoh berikut menunjukkan bagaimana dua middleware dapat digunakan `context.Context` untuk meneruskan informasi ke tumpukan. 

```
import "context"
import "github.com/aws/smithy-go/middleware"

// ...

type customKey struct {}

func GetCustomKey(ctx context.Context) (v string) {
    v, _ = middleware.GetStackValue(ctx, customKey{}).(string)
    return v
}

func SetCustomKey(ctx context.Context, value string) context.Context {
    return middleware.WithStackValue(ctx, customKey{}, value)
}

// ...

var customInitalize = middleware.InitializeMiddlewareFunc("customInitialize", func(
    ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
) (
    out middleware.InitializeOutput, metadata middleware.Metadata, err error,
) {
    ctx = SetCustomKey(ctx, "my-custom-value")
    
    return next.HandleInitialize(ctx, in)
})

var customBuild = middleware.BuildMiddlewareFunc("customBuild", func(
    ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler,
) (
    out middleware.BuildOutput, metadata middleware.Metadata, err error,
) {
    customValue := GetCustomKey(ctx)
    
    // use customValue

    return next.HandleBuild(ctx, in)
})
```

### Metadata Disediakan oleh SDK
<a name="metadata-provided-by-the-sdk"></a>

 AWS SDK untuk Go Menyediakan beberapa nilai metadata yang dapat diambil dari konteks yang disediakan. Nilai-nilai ini dapat digunakan untuk mengaktifkan middleware yang lebih dinamis yang memodifikasi perilakunya berdasarkan layanan eksekusi, operasi, atau wilayah target. Beberapa kunci yang tersedia disediakan dalam tabel di bawah ini: 


|  Kunci  |  Retriever  |  Deskripsi  | 
| --- | --- | --- | 
|  ServiceID  |  [GetServiceID](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/middleware#GetServiceID)  |  Ambil pengenal layanan untuk tumpukan eksekusi. Ini dapat dibandingkan dengan ServiceID konstanta paket klien layanan.  | 
|  OperationName  |  [GetOperationName](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/middleware#GetOperationName)  |  Ambil nama operasi untuk tumpukan eksekusi.  | 
|  Pencatat  |  [GetLogger](https://pkg.go.dev/github.com/aws/smithy-go/middleware#GetLogger)  |  Ambil logger yang dapat digunakan untuk logging pesan dari middleware.  | 

## Melewati Metadata Ke Tumpukan
<a name="passing-metadata-up-the-stack"></a>

 [Anda dapat meneruskan metadata melalui tumpukan dengan menambahkan kunci metadata dan pasangan nilai menggunakan middleware.metadata.](https://pkg.go.dev/github.com/aws/smithy-go/middleware#Metadata) Setiap langkah middleware mengembalikan struktur output, metadata, dan kesalahan. Middleware kustom Anda harus mengembalikan metadata yang diterima dari memanggil handler berikutnya di langkah tersebut. Ini memastikan bahwa metadata yang ditambahkan oleh middleware hilir menyebar ke aplikasi yang menjalankan operasi layanan. Metadata yang dihasilkan dapat diakses oleh aplikasi pemanggilan baik dengan bentuk output operasi melalui anggota struktur. `ResultMetadata` 

 Contoh berikut menunjukkan bagaimana middleware kustom dapat menambahkan metadata yang dikembalikan sebagai bagian dari output operasi. 

```
import "context"
import "github.com/aws/aws-sdk-go-v2/service/s3"
import "github.com/aws/smithy-go/middleware"

// ...

type customKey struct{}

func GetCustomKey(metadata middleware.Metadata) (v string) {
    v, _ = metadata.Get(customKey{}).(string)
    return v
}

func SetCustomKey(metadata *middleware.Metadata, value string) {
    metadata.Set(customKey{}, value)
}

// ...

var customInitalize = middleware.InitializeMiddlewareFunc("customInitialize", func (
    ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
) (
    out middleware.InitializeOutput, metadata middleware.Metadata, err error,
) {
    out, metadata, err = next.HandleInitialize(ctx, in)
    if err != nil {
        return out, metadata, err
    }
    
    SetCustomKey(&metadata, "my-custom-value")
    
    return out, metadata, nil
})

// ...

client := s3.NewFromConfig(cfg, func (options *s3.Options) {
    options.APIOptions = append(options.APIOptions, func(stack *middleware.Stack) error {
        return stack.Initialize.Add(customInitalize, middleware.After)
    })
})

out, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
    // input parameters
})
if err != nil {
    // handle error
}

customValue := GetCustomKey(out.ResponseMetadata)
```